如何使用 Mockito 从模拟构造中返回真实对象

问题描述 投票:0回答:1

我想使用 Mockito 5.9 从模拟构造中返回一个真实的对象,但我尝试过的任何方法都不起作用。

我第一次尝试这个:

    private static class Foo {
        private final int field;

        Foo(int field) {
            this.field = field;
        }

        int getField() {
            return field;
        }
    }

    @Test
    public void test() {
        Foo spy = new Foo(5);
        try (var ignored = mockConstruction(Foo.class, withSettings()
                .spiedInstance(spy))) {
            Foo foo = new Foo(0);
            int field = foo.getField();
            Assert.assertEquals(5, field);
        }
    }

但是当我运行它时测试失败了,说:

java.lang.AssertionError: 
Expected :5
Actual   :0

这与我需要的相反。

我也尝试过这个测试代码:

    @Test
    public void test() {
        try (var ignored = mockConstruction(Foo.class, withSettings()
                .useConstructor(5)
                .defaultAnswer(CALLS_REAL_METHODS))) {
            Foo foo = new Foo(0);
            int field = foo.getField();
            Assert.assertEquals(5, field);
        }
    }

但它因同样的问题而失败。我可以理解为什么这个特定选项可能不起作用,因为调用构造函数可能会触发存根行为,这是没有意义的。

我尝试的第三件事是这个,但同样的问题:

    @Test
    public void test() {
        Foo spy = mock(Foo.class, withSettings()
                .useConstructor(5)
                .defaultAnswer(CALLS_REAL_METHODS));
        try (var ignored = mockConstruction(Foo.class, withSettings()
                .spiedInstance(spy))) {
            Foo foo = new Foo(0);
            int field = foo.getField();
            Assert.assertEquals(5, field);
        }
    }

似乎

mockConstruction()
调用忽略了我正在配置的设置,这似乎是一个错误。知道这是否是一个错误或者是否有其他方法可以做到这一点?

我正在测试的真实代码肯定存在设计问题,但无论如何我都会检查 Mockito 是否有错误。

java mockito
1个回答
0
投票

不支持使用

mockConstruction()
直接操作构造函数行为以返回具有特定状态的真实对象,一个好的方法可能涉及关注可以控制的内容以及对象在构造后的行为方式。

第一步:抓住生产资料(写一个工厂类或者methpd)

    // this allows you to mock the factory instead of the constructor directly.
    public class FooFactory {
        public Foo createFoo(int field) {
            return new Foo(field);
        }
    }

第2步:使用FooFactory

    public class Bar {
      private FooFactory fooFactory;

      // injection of the factory
      public Bar(FooFactory fooFactory) {
        this.fooFactory = fooFactory;
      }

      public void performAction() {
        Foo foo = fooFactory.createFoo(10); // make Foo with the Factory
        // do some kung Foo
      }
    }

第3步:进行嘲笑(在某些测试中嘲笑工厂)

    public class YourTestClass {
      private FooFactory fooFactory = mock(FooFactory.class);
      private YourClassUnderTest classUnderTest =
          new YourClassUnderTest(fooFactory); // dependency injection

      @Test
      public void testFooCreationWithMockedFactory() {
        Foo fooWith5 = new Foo(5);

        when(fooFactory.createFoo(anyInt()))
            .thenReturn(fooWith5); // control the Foo object

        // trigger Foo creation
        int field = classUnderTest.someMethodThatCreatesFoo();

        Assert.assertEquals(5, field); // verify
      }
    }
© www.soinside.com 2019 - 2024. All rights reserved.