196

Spring 3.1.4.RELEASE と Mockito 1.9.5 を使用しています。私の春のクラスには次のものがあります。

@Value("#{myProps['default.url']}")
private String defaultUrl;

@Value("#{myProps['default.password']}")
private String defaultrPassword;

// ...

現在、次のように設定しているJUnitテストから:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:test-context.xml" })
public class MyTest 
{ 

「defaultUrl」フィールドの値をモックしたいと思います。他のフィールドの値をモックしたくないことに注意してください。「defaultUrl」フィールドのみをそのままにしておきたいのです。また、私のクラスには明示的な「セッター」メソッド (例: setDefaultUrl) がなく、テストのためだけにメソッドを作成したくないことにも注意してください。

これを考えると、その 1 つのフィールドの値をモックするにはどうすればよいでしょうか?

4

8 に答える 8

221

ReflectionTestUtils.setFieldコードに一切の変更を加えるのを避けるために、Spring の魔法を使用できます。

Michał Stochmalからのコメントは、例を提供します。

テスト中ReflectionTestUtils.setField(bean, "fieldName", "value");にメソッドを呼び出す前に使用します。bean

詳細については、このチュートリアルを参照してください。ただし、この方法は非常に使いやすいため、おそらく必要ないでしょう。

アップデート

Spring 4.2.RC1 の導入以来、クラスのインスタンスを提供することなく静的フィールドを設定できるようになりました。ドキュメントのこの部分とこのコミットを参照してください。

于 2014-04-18T21:38:44.013 に答える
151

@Value フィールドをモックする方法をいつも忘れているため、この SO 投稿にアクセスしたのは 3 回目です。受け入れられた答えは正しいですが、「setField」呼び出しを正しく行うには常に時間が必要なので、少なくとも私自身のために、ここにスニペットの例を貼り付けます。

生産クラス:

@Value("#{myProps[‘some.default.url']}")
private String defaultUrl;

テストクラス:

import org.springframework.test.util.ReflectionTestUtils;

ReflectionTestUtils.setField(instanceUnderTest, "defaultUrl", "http://foo");
// Note: Don't use MyClassUnderTest.class, use the instance you are testing itself
// Note: Don't use the referenced string "#{myProps[‘some.default.url']}", 
//       but simply the FIELDs name ("defaultUrl")
于 2016-03-30T12:20:25.750 に答える
39

この魔法の Spring Test アノテーションを使用できます。

@TestPropertySource(properties = { "my.spring.property=20" }) 

org.springframework.test.context.TestPropertySourceを参照

たとえば、これはテスト クラスです。

@ContextConfiguration(classes = { MyTestClass.Config.class })
@TestPropertySource(properties = { "my.spring.property=20" })
public class MyTestClass {

  public static class Config {
    @Bean
    MyClass getMyClass() {
      return new MyClass ();
    }
  }

  @Resource
  private MyClass myClass ;

  @Test
  public void myTest() {
   ...

そして、これはプロパティを持つクラスです:

@Component
public class MyClass {

  @Value("${my.spring.property}")
  private int mySpringProperty;
   ...
于 2018-10-03T08:04:40.500 に答える
37

プロパティ構成をテストクラスにモックすることもできます

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:test-context.xml" })
public class MyTest 
{ 
   @Configuration
   public static class MockConfig{
       @Bean
       public Properties myProps(){
             Properties properties = new Properties();
             properties.setProperty("default.url", "myUrl");
             properties.setProperty("property.value2", "value2");
             return properties;
        }
   }
   @Value("#{myProps['default.url']}")
   private String defaultUrl;

   @Test
   public void testValue(){
       Assert.assertEquals("myUrl", defaultUrl);
   }
}
于 2014-04-22T16:00:22.400 に答える
34

クラス @Valueを使用する代わりに、注釈付きフィールドをパラメーターとしてコンストラクターに渡すという関連する解決策を提案したいと思います。ReflectionTestUtils

これの代わりに:

public class Foo {

    @Value("${foo}")
    private String foo;
}

public class FooTest {

    @InjectMocks
    private Foo foo;

    @Before
    public void setUp() {
        ReflectionTestUtils.setField(Foo.class, "foo", "foo");
    }

    @Test
    public void testFoo() {
        // stuff
    }
}

これを行う:

public class Foo {

    private String foo;

    public Foo(@Value("${foo}") String foo) {
        this.foo = foo;
    }
}

public class FooTest {

    private Foo foo;

    @Before
    public void setUp() {
        foo = new Foo("foo");
    }

    @Test
    public void testFoo() {
        // stuff
    }
}

このアプローチの利点: 1) 依存コンテナーなしで Foo クラスをインスタンス化できる (これは単なるコンストラクターです)、2) テストを実装の詳細に結合していません (リフレクションにより、文字列を使用してフィールド名に結び付けられます。フィールド名を変更すると問題が発生する可能性があります)。

于 2018-03-01T21:56:07.033 に答える
28

以下のコードを使用しましたが、うまくいきました:

@InjectMocks
private ClassABC classABC;

@Before
public void setUp() {
    ReflectionTestUtils.setField(classABC, "constantFromConfigFile", 3);
}

参考:https ://www.jeejava.com/mock-an-autowired-value-field-in-spring-with-junit-mockito/

于 2019-06-14T09:22:01.087 に答える
0

可能な限り、フィールドの可視性をパッケージ保護として設定して、テスト クラスからアクセスできるようにします。Guava の@VisibleForTestingアノテーションを使用することを文書化します (次の人がなぜ非公開ではないのか疑問に思う場合に備えて)。このようにして、フィールドの文字列名に依存する必要がなくなり、すべてがタイプ セーフのままになります。

学校で教えられた標準的なカプセル化の慣行に反することはわかっています。しかし、チーム内でこの方向に進むという合意が得られるとすぐに、それが最も現実的な解決策であることがわかりました。

于 2020-11-25T08:26:22.517 に答える