Is it really a bad practice to mock a POJO (value object) if you don’t care about what it contains?

In the advice of Mockito about how to write good tests, it is written that we should not mock value objects (https://github.com/mockito/mockito/wiki/How-to-write-good-tests#dont-mock-value-objects). They even say

Because instantiating the object is too painful !? => not a valid
reason.

But I don’t understand. What if we really don’t care about what that object contain?
Let’s just say that I have a value object class “Foo” that doesn’t have simple constructors (it has an all-args constructor and contains objects that also need all-args constructors).
Let’s also say I have the following service:

public class MyService {
    private SomeService someService;
    private OtherService otherService;

    public void myAwesomeMethod() {
        Foo foo = someService.getFoo();
        someOtherService.doStuff(foo);
    }
}

And I need to test that method. Clearly here I don’t care about what foo contains because I just pass it to another method. If I want to test it should I really create a foo object with nested constructors/builders? For me it would be really easy to mock foo even if it is a POJO :

public class MyServiceTest {
    @InjectMocks
    MyService myService;

    @Mock
    private SomeService someService;

    @Mock
    private OtherService otherService;

    @Test
    public void testMyAwesomeMethod() {
        Foo mockedFoo = Mockito.mock(Foo.class);

        Mockito.when(someService.getFoo()).thenReturn(mockedFoo);

        Mockito.verify(otherService).doStuff(mockedFoo);
    }

}

But then it wouldn’t respect the guidelines given by Mockito. Is there another alternative?

10

Stubs (that you’ve called mocks in your question) exist for a reason: they make it possible to replace business code from the classes you depend on in the method you’re testing by some very basic statements which provide enough data for the tested method. Mocks, just like stubs, replace business logic by custom logic required for the tests.

  • If a POJO doesn’t have business code (i.e. if it’s also a data object), stubs and mocks would be useless. Using such data objects in tests should be quite easy. If the method needs a data object in input, just create one in the test.

    Some data objects may be very large, containing dozens of properties. In some languages, you can partially initialize a data object by setting only the properties you need during the test; in other languages, you need to fully initialize it. If this is your case, creating a simple static method which creates the data object with the default values and reusing this method all over the tests could be a solution.

  • If a POJO contains business code, you should isolate your unit tests from it, like you would do for any other class. Here, stubs and mocks are fine, and it doesn’t make a difference if the mocked object is a POJO or something else.

6

The best line from your link in my opinion is

Don’t mock everything, it’s an anti-pattern

If everything is mocked, are we really testing the production code?
Don’t hesitate to not mock!

Usually you want to test your code with real inputs and expected outputs and usually these will be data structures or pojos/pocos

ie.

actual = myfunc(input)
Assert.AreEqual(actual, expected)

It doesn’t make sense to mock that input or output because its set up specifically for that test. You always care about it.

In your example you have no input, output or indeed logic to perform. Even if you have a real example where code just passes an object from one service to another, surely you want to test edge cases like nulls or a very large object? You should care about what that object is.

You might be running into a code smell.

Clearly here I don’t care about what foo contains because I just pass it to another method.

The thing that stands out to me in this example is that your code doesn’t even care that the object being exchanged is a Foo.

public class MyService<T> {
    private java.util.function.Supplier<? extends T> someService;
    private java.util.function.Consumer<? super T> otherService;

    public void myAwesomeMethod() {
        T foo = someService.get();
        someOtherService.accept(foo);
    }
}

Then, in your unit test, instead of trying to use a Foo, or to create a test double that you can use in place of a Foo, you can inject a Supplier/Consumer pair.

Let’s just say that I have a value object class “Foo” that doesn’t have simple constructors (it has an all-args constructor and contains objects that also need all-args constructors).

Another common pattern is to use test data builders to create the values that you need. Test data builders typically use fluent interfaces to communicate within a test which details of the object are important in the context of the test.

@Test
public void testMyAwesomeMethod() {
    Foo mockedFoo = new FooBuilder().anyOldFoo();

    Mockito.when(someService.getFoo()).thenReturn(mockedFoo);

    Mockito.verify(otherService).doStuff(mockedFoo);
}

Here, the interaction with the builder articulates that the behavior of this test shouldn’t depend on the specific foo value.

If you squint, you might see that the test is asserting a property

public void testMyAwesomeMethod() {
    for (Foo candidate : allPossibleFoo()) {
        Mockito.when(someService.getFoo()).thenReturn(candidate);
        // ...
    }
}

None of these builder approaches directly solves the problem of invoking the fool constructor; all the builder does is move that complexity out of the test.

You are somewhat correct.

When you mock an object, you typically stub out the methods to return canned values instead. But there isn’t really a good reason to do this for a value object, just use the value object instead.

However, in this particular scenario you aren’t stubbing out any of the methods. You are just verifying that the same object returned from one function gets passed to another. So you don’t get the disadvantages of mocking the value object.

Nevertheless, you almost certainly should have test code that constructs a Foo. The test for SomeService should probably assertEquals the result of getFoo with some constructed Foo. The test for OtherService should pass some constructed Foo object to doStuff. You’ve got to have code somewhere that constructs Foo objects for those tests, so you should be able to readily refactor that construction code into a place where it can be reused.

However, in general, it is suspicious that MyService doesn’t want to call any methods on Foo. This is often a sign that MyService shouldn’t be dealing with Foo at all. If all MyService does it take an object from SomeService and pass it to OtherService what’s the point of MyService? Simplify your code and connect the two services directly.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật