Git Product home page Git Product logo

to-string-verifier's Introduction

To String Verifier

Maven Central Build Status Javadocs

Getting Started

Get To String Verifier

Maven:

<dependency>
    <groupId>com.jparams</groupId>
    <artifactId>to-string-verifier</artifactId>
    <version>1.x.x</version>
    <scope>test</scope>
</dependency>

Gradle:

testImplementation 'com.jparams:to-string-verifier:1.x.x'

What is To String Verifier?

To String Verifier is the easiest, most convenient way to test the toString method on your class. toString methods are incredibly important for logging and debugging purposes, yet when it comes to testing, it is often forgotten or ignored. It is very easy to add a new field to your class and forget to update the toString method. Without tests in place, you won’t know something is missing until you are sitting looking through logs or debugging your application and by that time its already too late.

Write a Test

Writing a test is easy! In most cases you want to ensure that your toString method contains the class name and all the fields. Let's look at how we would write this test!

@Test
public void testToString()
{
    ToStringVerifier.forClass(User.class)
                    .withClassName(NameStyle.SIMPLE_NAME)
                    .verify();
}

Oh! A user object. I would not want to include the password in the toString, how do I exclude it from my test?

@Test
public void testToString()
{
    ToStringVerifier.forClass(Person.class)
                    .withClassName(NameStyle.SIMPLE_NAME)
                    .withIgnoredFields("password")
                    .withFailOnExcludedFields(true) // with this set true, if a developer accidently adds the password to the toString(), the unit test will fail
                    .verify();
}

To String Verifier is incredibly configurable, so take a look at the Java Docs for more options.

Package Scan

Some times you want to test a number of classes at once, or maybe all classes in a package. Well, we have you covered!

Testing multiple classes is as easy as: ToStringVerifier.forClasses(Person.class, Animal.class, Tree.class).verify()

To scan an entire package:

@Test
public void testToString()
{
    boolean scanRecursively = true; // when set to true, this will scan the given package and all subpackages.
    Predicate<Class<?>> predicate = (clazz) -> clazz.getName().endsWith("Model"); // optional parameter
    ToStringVerifier.forPackage("my.most.awesome.package", scanRecursively, predicate).verify();
}

Presets

To String Verifier also comes with a number of Vendor presets. These presets describe how different vendors style and format their toString output. Just tell us the Vendor preset to apply and begin testing!

ToStringVerifier.forClass(Person.class).withPreset(Presets.ECLIPSE).verify()

Here are all the Vendor presets available out of the box:

  • IntelliJ default style
  • Eclipse default style
  • Guava's MoreObjects toStringHelper.
  • Apache's ToStringBuilder. Supported ToStringStyles include:
    • JSON_STYLE
    • NO_CLASS_NAME_STYLE
    • DEFAULT_STYLE
    • MULTI_LINE_STYLE
    • SHORT_PREFIX_STYLE

Compatibility

This library is compatible with Java 8 and above.

to-string-verifier's People

Contributors

dependabot-preview[bot] avatar jparams avatar riggs333 avatar thunderforge avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

to-string-verifier's Issues

NullPointerException when class has field of type SortedSet

To String Verifier Version: 1.4.2

java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

Given a class with field of type java.util.SortedSet

import com.google.common.base.MoreObjects;

import java.util.SortedSet;
import java.util.TreeSet;

public class SortedSetContainer {

    private SortedSet<String> elements = new TreeSet<>();

    public void setElements(SortedSet<String> elements) {
        this.elements = elements;
    }

    public SortedSet<String> getElements() {
        return elements;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("elements", elements)
                .toString();
    }
}

When running To String Verifier

@Test
public void sortedSet() {
    ToStringVerifier.forClass(SortedSetContainer.class).verify();
}

A NullPointerException is thrown

java.lang.NullPointerException
	at com.jparams.verifier.tostring.ToStringVerifier.getFieldValues(ToStringVerifier.java:456)
	at com.jparams.verifier.tostring.ToStringVerifier.verifyField(ToStringVerifier.java:410)
	at com.jparams.verifier.tostring.ToStringVerifier.lambda$verify$5(ToStringVerifier.java:370)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
	at com.jparams.verifier.tostring.ToStringVerifier.verify(ToStringVerifier.java:373)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:479)
	at com.jparams.verifier.tostring.ToStringVerifier.verify(ToStringVerifier.java:336)

Interestingly when changing the type of the field to java.util.Set then the test passes.

Commons-lang3 toString style does not fit the expected style of to-string-verifier

Hello,

we use apache common-lang3 to generate toString presentations. Starting with commons-lang3 3.11 the output was changed for maps. See https://issues.apache.org/jira/browse/LANG-1543
If we update the apache dependency our test will failed due the to-string-verifier does not expect this new style.

Please fix this.

Example:

public class Example {

	private Map<String, Integer> exampleMap;

	public Map<String, Integer> getExampleMap() {
		return exampleMap;
	}

	public void setExampleMap(Map<String, Integer> exampleMap) {
		this.exampleMap = exampleMap;
	}

	@Override
	public String toString() {
		return new ReflectionToStringBuilder(this, ToStringStyle.JSON_STYLE).append("class", this.getClass().getCanonicalName())
				.toString();
	}
}
@Test
	public void testExampleToString() {
		ToStringVerifier.forClass(Example.class).verify();
	}

the result with to-string-verifier 1.4.8 is:
java.lang.AssertionError:

Failed verification:

com.Example

Expected auto generated toString:
{"class":"com.Example","exampleMap":{"3585d9b7-9589-4a2c-a291-151b6d5551df":-1387581510}}

To contain fields with values:
  - exampleMap: {3585d9b7-9589-4a2c-a291-151b6d5551df=-1387581510

The problem seems to be the equals-sign "=". It was replaced with ":" for legal json representation.

With kind regards
Dennis

[Refactoring] Remove obsolete final modifier from parameters and local variables

I noticed the use of the final modifier for every(?) method parameter and local variables.
This is almost unnecessary and clutters the codes making in less readable, in my opinion.
Here is some reference about the use of final in those cases: https://www.javaspecialists.eu/archive/Issue207.html

Consider removing the use of final unless there is a valid reason to keep it.
I know this change will touch nearly every file. But would be a huge cleanup for the whole codebase. :-)

What do you think?

Illegal reflective access operation with Java 11

I run the tests of my project with Java 11, and I have the following warnings:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.jparams.object.builder.provider.ObjectProvider (file:/C:/Users/.../.m2/repository/com/jparams/object-builder/2.3.1/object-builder-2.3.1.jar) to constructor java.lang.Class(java.lang.ClassLoader,java.lang.Class)
WARNING: Please consider reporting this to the maintainers of com.jparams.object.builder.provider.ObjectProvider
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

Could you fix this problem to remain compatible with Java 11 and above?

Config option to finetune delimiters between attributes/objects

We're using a custom ToStringBuilder that adds some tweaking to the output/indention. If the attribute is a complex object, it adds 3 spaces after the newline - so it's better readable. to-string-verifier fails on this since it does not expect those 3 spaces to be there. It would be great, if this check for spaces could be exposed to the outside world, so someone could tweak it. Maybe one could also think about, to offer an option, to ignore such whitespaces completely and just focus on the textual parts like attributes, commas etc. WDYT?

Apache related presets with hashCode included uses hash comparison logic different from the one of Apache

With latest version of ToStringVerifier (1.4.4) the verifications with Apache presets with switched "hashcode" (com.jparams.verifier.tostring.preset.Presets#APACHE_TO_STRING_BUILDER_NO_CLASS_NAME_STYLE and com.jparams.verifier.tostring.preset.Presets#APACHE_TO_STRING_BUILDER_DEFAULT_STYLE) are failing.

The code:

public String toString()
  {
    return new ToStringBuilder(this, MULTI_LINE_STYLE)
        .append("id", id)
        .append("title", title)
        .append("plannedDate", plannedDate)
        .toString();
  }

The test:

ToStringVerifier
        .forClass(Demo.class)
        .withPreset(Presets.APACHE_TO_STRING_BUILDER_MULTI_LINE_STYLE)
        .withOnlyTheseFields("id", "title", "plannedDate")
        .verify();

The result:

java.lang.AssertionError: 

Failed verification:
org.vkulinski.demolot.domain.Demo

Expected auto generated toString:
org.vkulinski.demolot.domain.Demo@5dd91bca[
  id=-4025896784895923501
  title=981da480-a039-4248-b8f3-6b4e469fbb65
  plannedDate=2018-12-14
]

To contain hash code: 41bf187d

	at com.jparams.verifier.tostring.ToStringVerifier.verify(ToStringVerifier.java:348)
	at org.vkulinski.demolot.domain.DemoTest.testToString(DemoTest.java:97)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
	at org.junit.rules.RunRules.evaluate(RunRules.java:20)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:79)
	at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:85)
	at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
	at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
	at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:53)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

The reason - System.identityHashCode is used to transform the hash code into string on Apache side (see org.apache.commons.lang3.builder.ToStringStyle#appendIdentityHashCode), while Integer.toHexString is used for hash code verification on the library side (see com.jparams.verifier.tostring.ToStringVerifier#verifyHashCode).

A remark: I'm using apache commons version 3.7 (it can be a recent change in this version).

Fields of type Instant are not supported.

The following test fails:

public class InstantNotSupportedTest
{

   private static class ClassWithInstant {
      private Instant theInstant;

      @Override
      public String toString()
      {
         return "ClassWithInstant{" + "theInstant=" + theInstant + '}';
      }
   }

   @Test
   public void testToString() {
      ToStringVerifier.forClass(ClassWithInstant.class)
         .withClassName(NameStyle.SIMPLE_NAME)
         .verify();
   }

}

It throws this error: java.time.DateTimeException: Invalid value for NanoOfSecond (valid values 0 - 999999999): 1361563254

Of course, I could use sth like ".withPrefabValue(Instant.class, Instant.now())", but what if my class contains multiple fields of type Instant? The test will then not fail when I switch the field references in the toString() implementation.
What about adding a method like "withPrefabValueFactory(T, Supplier)"?

NullPointerException on BigInteger

Steps to reproduce:

package com.jparams.verifier.tostring;

import org.junit.jupiter.api.RepeatedTest;

import java.math.BigInteger;

final class ToStringVerifier_BigIntegerTest {
  @RepeatedTest(15)
  void testBigInteger_toStringMethod() {
    ToStringVerifier.forClass(BigInteger.class).verify();
  }
}

Expected results:

  1. No failure.

Actual results:

  1. NOK: NullPointerException

Stack trace:
Stack trace when run from IntelliJ IDEA 2020.1.1 Preview:

java.lang.NullPointerException
	at java.math.BigInteger.toString(BigInteger.java:3797)
	at java.math.BigInteger.toString(BigInteger.java:3959)
	at com.jparams.verifier.tostring.ToStringVerifier.verify(ToStringVerifier.java:419)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:479)
	at com.jparams.verifier.tostring.ToStringVerifier.verify(ToStringVerifier.java:399)
	at com.jparams.verifier.tostring.ToStringVerifier_BigIntegerTest.testBigInteger_toStringMethod(ToStringVerifier_BigIntegerTest.java:11)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:675)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:125)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:132)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:124)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestTemplateMethod(TimeoutExtension.java:81)
	at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:104)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:62)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:43)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:35)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:202)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:198)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:69)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor.execute(NodeTestTask.java:198)
	at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.execute(TestTemplateTestDescriptor.java:138)
	at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.lambda$execute$2(TestTemplateTestDescriptor.java:106)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
	at java.util.stream.IntPipeline$4$1.accept(IntPipeline.java:250)
	at java.util.stream.Streams$RangeIntSpliterator.forEachRemaining(Streams.java:110)
	at java.util.Spliterator$OfInt.forEachRemaining(Spliterator.java:693)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
	at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:270)
	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
	at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.execute(TestTemplateTestDescriptor.java:106)
	at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.execute(TestTemplateTestDescriptor.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
	at java.util.ArrayList.forEach(ArrayList.java:1257)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
	at java.util.ArrayList.forEach(ArrayList.java:1257)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
	at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
	at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)

Environment:

  • JDK 8 (1.8.0_211).

String-formatter is erroneously applied to collections (and maps) with type string

I have a class containing both a field of type String and of type Collection.

IntelliJ (Template "String concat (+) and super.toString()") generates the following code for this:

      @Override
      public String toString()
      {
         return "ClassWithStringAndStringCollection{" + "theString='" + theString + '\'' + ", theStringCollection="
            + theStringCollection + '}';
      }

When I write a test which checks that the string value is surrounded by apostrophs by configuring a corresponding formatter for type String, this formatter is erroneously also applied to each value in the collection, leading to the following failure:

Failed verification:
CustomStringFormatterShouldNotBeAppliedToCollectionsForIntelliJTest$ClassWithStringAndStringCollection

Expected auto generated toString:
ClassWithStringAndStringCollection{theString='ece92ceb-3625-4268-b18d-0a95bdc12b26', theStringCollection=[cf517611-c145-4258-8a3c-766ff13f3d6c]}

To contain fields with values:
  - theStringCollection: 'cf517611-c145-4258-8a3c-766ff13f3d6c'

Here is a test to reproduce:

import java.util.List;

import org.junit.Test;

import com.jparams.verifier.tostring.ToStringVerifier;
import com.jparams.verifier.tostring.preset.IntelliJPreset;

public class CustomStringFormatterShouldNotBeAppliedToCollectionsForIntelliJTest
{

   private static class ClassWithStringAndStringCollection
   {
      private String theString;
      private List<String> theStringCollection;

      @Override
      public String toString()
      {
         return "ClassWithStringAndStringCollection{" + "theString='" + theString + '\'' + ", theStringCollection="
            + theStringCollection + '}';
      }
   }

   @Test
   public void testToString() {
      ToStringVerifier.forClass(ClassWithStringAndStringCollection.class)
         .withPreset(new IntelliJPreset())
         .withFormatter(String.class, str -> '\'' + str  + '\'')
         .verify();
   }

}

Using a Map<String, String> instead of List produces a similar error.

Failed String Comparisons for List of Strings while attempting to upgrade to 1.4.8

As stated on the title we are seeing failures on the comparison of Lists of String objects, in our case, due to omission of double quotes. We tried to pass in a String formatter to add the double quotes but issue remains. We think this stems from this fix #24. Here is how to replicate it:

@test
void testListOfStrings() {
ToStringVerifier.forClass(HasListField.class)
.withPreset(Presets.APACHE_TO_STRING_BUILDER_JSON_STYLE)
.verify();
}

class HasListField{
private List strings;

public HasListField(List<String> strings) {
  this.strings = strings;
}

public List<String> getStrings() {
  return strings;
}

@Override
public String toString() {
  return new Gson().toJson(this);
}

}

Test does not fail when excluded field has a different label in toString

Let's assume I have a field named "password", but it is labeled as "pwd" in the toString() method. I would expect that the following test should fail, but it passes. Maybe this could be fixed by failing if the test contains any unexpected fields? (I did not find an option for this.)

import org.junit.Test;

import com.jparams.verifier.tostring.NameStyle;
import com.jparams.verifier.tostring.ToStringVerifier;

public class PasswordWithWrongFieldLabelShouldThrowTest
{

   private static class ClassWithPassword
   {
      private String password;

      @Override
      public String toString()
      {
         return "ClassWithPassword{" + "pwd=" + password + '}';
      }
   }

   @Test
   public void testToString() {
      ToStringVerifier.forClass(ClassWithPassword.class)
         .withClassName(NameStyle.SIMPLE_NAME)
         .withIgnoredFields("password")
         .withFailOnExcludedFields(true)
         .verify();
   }

}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.