简体   繁体   English

带有@RunWith(PowerMockRunner.class)批注的测试类在扩展另一个类时两次运行测试用例

[英]Test Class with @RunWith(PowerMockRunner.class) annotation runs test cases twice when extending another class

I am working on unit tests. 我正在进行单元测试。 Our project is working with the Play! 我们的项目正在与Play合作! framework. 框架。 The unit tests are written in Java. 单元测试是用Java编写的。 Our team has encountered a problem where we have been experiencing duplicate test runs for test classes which are annotated with @RunWith(PowerMockRunner.class) and extend another class. 我们的团队遇到一个问题,即我们一直在使用@RunWith(PowerMockRunner.class)注释并扩展另一个类的测试类经历重复的测试运行。

Our main set up for test classes are as follows: 我们对测试类的主要设置如下:

A Unit Test Harness: Contains functionality shared among various test cases. 单元测试工具:包含各种测试用例之间共享的功能。 Also contains commonly used fields. 还包含常用字段。

@Ignore
@RunWith(PowerMockRunner.class)
@PrepareForTest(SomeStaticClass.class)
public abstract class UnitTestHarness {
    //Bunch of setup code...
}

A Test Class: Contains the test cases for the class we're testing. 测试类:包含我们正在测试的类的测试用例。

public class TestClass extends UnitTestHarness {
    @Test
    public void testSomething(){
        //Perform some tests...
    }
}

As you can see, TestClass extends UnitTestHarness which has the annotation. 如您所见,TestClass扩展了具有批注的UnitTestHarness。 When TestClass is run by the play "test-only" command, the following output is returned: 当通过play“ test-only”命令运行TestClass时,返回以下输出:

[info] somepackage.TestClass
[info] + testSomething
[info] 
[info] 
[info] Total for test somepackage.TestClass
[info] Finished in 0.055 seconds
[info] 1 tests, 0 failures, 0 errors
[info] somepackage.TestClass
[info] + testSomething
[info] 
[info] 
[info] Total for test somepackage.TestClass
[info] Finished in 0.001 seconds
[info] 4 tests, 0 failures, 0 errors
[info] Passed: Total 4, Failed 0, Errors 0, Passed 4
[success] Total time: 18 s, completed Apr 16, 2014 4:19:37 PM

Obviously, the tests are being run twice for some reason. 显然,由于某种原因,测试运行了两次。 I've read online that there have been some issues with the @RunWith annotation and extending classes, but I haven't been able to find a solution. 我已经在线阅读了@RunWith批注和扩展类的问题,但是我找不到解决方案。 I feel it is also import to note that if I move the annotation from UnitTestHarness to TestClass, the following output will be returned: 我觉得也很重要,要注意,如果我将注释从UnitTestHarness移到TestClass,将返回以下输出:

[info] somepackage.TestClass
[info] 
[info] 
[info] Total for test somepackage.TestClass
[info] Finished in 0.032 seconds
[info] 0 tests, 0 failures, 0 errors
[info] somepackage.TestClass
[info] + testSomething
[info] 
[info] 
[info] Total for test somepackage.TestClass
[info] Finished in 0.025 seconds
[info] 4 tests, 0 failures, 0 errors
[info] Passed: Total 4, Failed 0, Errors 0, Passed 4
[success] Total time: 13 s, completed Apr 16, 2014 4:47:28 PM

In this case, we can see that it's still trying to run some sort of tests, but it isn't actually running the additional 4 because the UnitTestHarness does not have the annotation. 在这种情况下,我们可以看到它仍在尝试运行某种测试,但实际上并未运行其他4个测试,因为UnitTestHarness没有注释。 I'm guessing this is because while in the first example the annotation was placed on the UnitTestHarness and was inherited by TestClass, in this example only the TestClass has the annotation so the tests are only run for that particular class. 我猜这是因为在第一个示例中,批注放置在UnitTestHarness上,并由TestClass继承,在此示例中,只有TestClass具有批注,因此仅针对该特定类运行测试。

Has anyone else seen this issue? 还有其他人看到过这个问题吗? Obviously we can make due with the second scenario, but that additional attempt to run those classes shouldn't be happening at all ideally. 显然,我们可以在第二种情况下进行尝试,但是理想情况下根本不应该再尝试运行这些类。 Is this a problem with the PowerMockRunner or the Play framework? 这是PowerMockRunner或Play框架的问题吗? The tests are also run twice when I run a mvn clean install or play test to run the entire test suite. 当我运行mvn全新安装或播放测试以运行整个测试套件时,这些测试也会运行两次。 Any possible solutions or suggestions would be greatly appreciated. 任何可能的解决方案或建议,将不胜感激。 Thank you all so much for your help. 非常感谢大家的帮助。

Suggested Solution #1 : Inject UnitTestHarness 建议的解决方案#1 :注入UnitTestHarness

I was able to get them not to run twice by using MockitoAnnotations.initMocks(this); 通过使用MockitoAnnotations.initMocks(this),我能够使它们不再运行两次。 instead of the annotation you mentioned. 而不是您提到的注释。 When you use the annotation, the tests still run twice. 当您使用注释时,测试仍将运行两次。 I tried to use this method described but ran into a variety of problems both with and without the annotation. 我尝试使用所描述的这种方法,但是在使用注释和不使用注释的情况下都遇到了各种问题。

1) This doesn't seem like the proper use of @InjectMocks. 1)这似乎不是@InjectMocks的正确使用。 I've used that annotation and it's really meant to be used when you have fields mocked out that you want to inject into another object which has a field of that type. 我已经使用了该批注,并且当您想将要注入到具有该类型字段的另一个对象中的字段模拟出来时,它实际上是要使用的。

2) I've found that the mock behaviors from the UnitTestHarness, when injected in this manner, don't transfer. 2)我发现,以这种方式注入时,来自UnitTestHarness的模拟行为不会转移。 Our Unit Test Harness sets up a current Http.Context and this does not transfer to our test case. 我们的单元测试工具会设置一个当前的Http.Context,这不会转移到我们的测试用例中。 In fact, a lot of the initialization that made UnitTestHarness useful would need to be transferred into an @Before method in the TestClass itself which defeats the purpose of having the harness in the first place I feel. 实际上,很多使UnitTestHarness有用的初始化都需要转移到TestClass本身的@Before方法中,这违背了我最初认为使用线束的目的。

3) All methods that we have and use in the harness will have to be made public for accessibility and accessed either by the instance of the harness or static calls in the TestClass itself. 3)我们必须将线束中拥有和使用的所有方法公开,以实现可访问性,并且必须通过线束实例或TestClass本身中的静态调用对其进行访问。 We would also need to either make fields in the harness public, or create mutators for a majority of them. 我们还需要公开线束中的字段,或者为其中大多数创建变量。

Overall I don't think this is a good solution to the problem we're having, but I appreciate your idea. 总的来说,我认为这不是解决我们所遇到问题的好方法,但我感谢您的想法。

Did you try to inject UnitTestHarness into TestClass using annotation @InjectMocks and call all necessary methods in method annotated by @Before? 您是否尝试使用注解@InjectMocks将UnitTestHarness注入TestClass并在@Before注释的方法中调用所有必需的方法? Remeber that when you use @InjectMocks, you also need add above the class name @RunWith(MockitoJUnitRunner.class). 请记住,在使用@InjectMocks时,还需要在类名称@RunWith(MockitoJUnitRunner.class)之上添加。 Here are some examples. 这里有一些例子。

Avoidance of inheritance is always a good choice. 避免继承始终是一个不错的选择。

Edit: 编辑:

It seems to me that the problem is not in the the library. 在我看来,问题不在图书馆。 I wrote some code and it's work fine: 我写了一些代码,一切正常:

public final class ClassWithStaticMethods {

   public static String returnString(){
       return "Sample text";
   }
}

@RunWith(PowerMockRunner.class)
@PrepareForTest(ClassWithStaticMethods.class)
public class UnitTestHarness {

    private String field1 = "field1";
    private String field2 = "field2";

    @Before
    public void setUp() {
        PowerMockito.mockStatic(ClassWithStaticMethods.class);
        when(ClassWithStaticMethods.returnString()).thenReturn("This static method is mocked!");
    }

    public List<String> createList() {
        List<String> list = Lists.newArrayList();
        list.add("firstElement");
        list.add("secondElement");
        list.add("thirdElement");

        return list;
    }

    public Point dummyPoint() {
        return new Point(2, 3);
    }

    public String getField1() {
        return field1;
    }

    public void setField1(String field1) {
        this.field1 = field1;
    }

    public String getField2() {
        return field2;
   }

    public void setField2(String field2) {
        this.field2 = field2;
    }
}


public class TestClass extends UnitTestHarness {

    private List<String> list;
    private Point dummyPoint;

    @Before
    public void setup() {
        list = createList();
        dummyPoint = dummyPoint();
    }

    @Test
    public void testSomething() {
        System.out.println("First test method. Value of field1 from UnitTestHarness is: " + getField1());
        setField1("New value");
        System.out.println("First test method. Value of field1 from UnitTestHarness is: " + getField1());
    }

    @Test
    public void testSomethingElse() {
        System.out.println("Second test method. Value of field2 from UnitTestHarness is: " + getField2());
    }

    @Test
    public void testStaticMockMethod() {
        System.out.println(ClassWithStaticMethods.returnString());
    }

    @Test
    public void testDummyPoint() {
        System.out.println(String.format("My point: %s, %s", dummyPoint.getX(), dummyPoint.getY()));
    }

    @Test
    public void testArray() {
        for (String string : list) {
            System.out.println("Array element:" + string);
        }
   }
}

This is my console output: 这是我的控制台输出:

Running service.TestClass
Array element:firstElement
Array element:secondElement
Array element:thirdElement
First test method. Value of field1 from UnitTestHarness is: field1
First test method. Value of field1 from UnitTestHarness is: New value
Second test method. Value of field2 from UnitTestHarness is: field2
This static method is mocked!
My point: 2.0, 3.0
Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.442 sec

Results :

Tests run: 5, Failures: 0, Errors: 0, Skipped: 0

Without the broader context of this problem it's hard to advise something more concrete, maybe you should add more code which is inside this classes? 没有这个问题的更广泛的上下文,很难建议更具体的东西,也许您应该添加更多在此类内部的代码?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 @RunWith(PowerMockRunner.class) 时出现 NoClassDefFoundError - NoClassDefFoundError when using @RunWith(PowerMockRunner.class) 问题在于@RunWith(PowerMockRunner.class) - the problem is with @RunWith(PowerMockRunner.class) RunWith(PowerMockRunner.class)不适用于包注释 - RunWith(PowerMockRunner.class) does not work with package annotation PowerMock从@RunWith(PowerMockRunner.class)批注引发异常 - PowerMock Throwing an Exception from @RunWith(PowerMockRunner.class) Annotation 没有@RunWith的模拟静态(PowerMockRunner.class) - mock static without @RunWith(PowerMockRunner.class) 使用@RunWith(PowerMockRunner.class)进行Junit测试失败 - “没有找到匹配的测试......” - Junit test with @RunWith(PowerMockRunner.class) fails - “No tests found matching..” @RunWith(PowerMockRunner.class)是否在每次测试之前为使用@Mock注释的成员注入新的模拟? - Does @RunWith(PowerMockRunner.class) inject new mocks for members annotated with @Mock prior to each test? @RunWith(PowerMockRunner.class)vs @RunWith(MockitoJUnitRunner.class) - @RunWith(PowerMockRunner.class) vs @RunWith(MockitoJUnitRunner.class) @RunWith(PowerMockRunner.class)说@RunWith不适用于方法 - @RunWith(PowerMockRunner.class) says @RunWith not applicable to method @RunWith(PowerMockRunner.class)与tycho surefire不兼容 - @RunWith(PowerMockRunner.class) do not work with tycho surefire
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM