Mocking Java enum to add a value to test fail case

前端 未结 10 1374
死守一世寂寞
死守一世寂寞 2020-11-28 23:55

I have an enum switch more or less like this:

public static enum MyEnum {A, B}

public int foo(MyEnum value) {
    switch(value) {
        case(A):          


        
相关标签:
10条回答
  • 2020-11-29 00:32

    First of all Mockito can create mock data which can be integer long etc It cannot create right enum as enum has specific number of ordinal name value etc so if i have an enum

    public enum HttpMethod {
          GET, POST, PUT, DELETE, HEAD, PATCH;
    }
    

    so i have total 5 ordinal in enum HttpMethod but mockito does not know it .Mockito creates mock data and its null all the time and you will end up in passing a null value . So here is proposed solution that you randomize the ordinal and get a right enum which can be passed for other test

    import static org.mockito.Mockito.mock;
    
    import java.util.Random;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.mockito.Matchers;
    import org.mockito.internal.util.reflection.Whitebox;
    import org.powermock.api.mockito.PowerMockito;
    import org.powermock.core.classloader.annotations.PrepareForTest;
    import org.powermock.modules.junit4.PowerMockRunner;
    
    import com.amazonaws.HttpMethod;
    
    
    
    
    //@Test(expected = {"LoadableBuilderTestGroup"})
    //@RunWith(PowerMockRunner.class)
    public class testjava {
       // private static final Class HttpMethod.getClass() = null;
        private HttpMethod mockEnumerable;
    
        @Test
        public void setUpallpossible_value_of_enum () {
            for ( int i=0 ;i<10;i++){
                String name;
                mockEnumerable=    Matchers.any(HttpMethod.class);
                if(mockEnumerable!= null){
                    System.out.println(mockEnumerable.ordinal());
                    System.out.println(mockEnumerable.name());
    
                    System.out.println(mockEnumerable.name()+"mocking suceess");
                }
                else {
                    //Randomize all possible  value of  enum 
                    Random rand = new Random();
                    int ordinal = rand.nextInt(HttpMethod.values().length); 
                    // 0-9. mockEnumerable=
                    mockEnumerable= HttpMethod.values()[ordinal];
                    System.out.println(mockEnumerable.ordinal());
                    System.out.println(mockEnumerable.name());
                }
            }
        }
    
    
    
    
    
    
    
        @Test
        public void setUpallpossible_value_of_enumwithintany () {
            for ( int i=0 ;i<10;i++){
                String name;
                mockEnumerable=    Matchers.any(HttpMethod.class);
                if(mockEnumerable!= null){
                    System.out.println(mockEnumerable.ordinal());
                    System.out.println(mockEnumerable.name());
    
                    System.out.println(mockEnumerable.name()+"mocking suceess");
                } else {
                   int ordinal;
                   //Randomize all possible  value of  enum 
                   Random rand = new Random();
                   int imatch =  Matchers.anyInt();
                   if(  imatch>HttpMethod.values().length)
                     ordinal = 0    ;
                   else
                    ordinal = rand.nextInt(HttpMethod.values().length);
    
                   // 0-9.  mockEnumerable=
                   mockEnumerable= HttpMethod.values()[ordinal];
                   System.out.println(mockEnumerable.ordinal());
                   System.out.println(mockEnumerable.name());       
                }
           }  
        }
    }
    

    Output :

    0
    GET
    0
    GET
    5
    PATCH
    5
    PATCH
    4
    HEAD
    5
    PATCH
    3
    DELETE
    0
    GET
    4
    HEAD
    2
    PUT
    
    0 讨论(0)
  • 2020-11-29 00:36

    Rather than using some radical bytecode manipulation to enable a test to hit the last line in foo, I would remove it and rely on static code analysis instead. For example, IntelliJ IDEA has the "Enum switch statement that misses case" code inspection, which would produce a warning for the foo method if it lacked a case.

    0 讨论(0)
  • 2020-11-29 00:36

    jMock (at least as of version 2.5.1 that I'm using) can do this out of the box. You will need to set your Mockery to use ClassImposterizer.

    Mockery mockery = new Mockery();
    mockery.setImposterizer(ClassImposterizer.INSTANCE);
    MyEnum unexpectedValue = mockery.mock(MyEnum.class);
    
    0 讨论(0)
  • 2020-11-29 00:43

    As you indicated in your edit, you can add the functionaliy in the enum itself. However, this might not be the best option, since it can violate the "One Responsibility" principle. Another way to achieve this is to create a static map which contains enum values as key and the functionality as value. This way, you can easily test if for any enum value you have a valid behavior by looping over all the values. It might be a bit far fetched on this example, but this is a technique I use often to map resource ids to enum values.

    0 讨论(0)
  • 2020-11-29 00:45

    If you can use Maven as your build system, you can use a much simpler approach. Just define the same enum with an additional constant in your test classpath.

    Let's say you have your enum declared under the sources directory (src/main/java) like this:

    package my.package;
    
    public enum MyEnum {
        A,
        B
    }
    

    Now you declare the exact same enum in the test sources directory (src/test/java) like this:

    package my.package
    
    public enum MyEnum {
        A,
        B,
        C
    }
    

    The tests see the testclass path with the "overloaded" enum and you can test your code with the "C" enum constant. You should see your IllegalArgumentException then.

    Tested under windows with maven 3.5.2, AdoptOpenJDK 11.0.3 and IntelliJ IDEA 2019.3.1

    0 讨论(0)
  • 2020-11-29 00:49

    I added an Unknown option to my enum, which I pass in during the test. Not ideal in every case, but simple.

    0 讨论(0)
提交回复
热议问题