2011-06-29 12 views

Odpowiedz

13

Jeśli naprawdę chcesz uniknąć dotykania tego kodu, możesz użyć Powermockito (PowerMock for Mockito).

Dzięki temu, między innymi, możesz mock the construction of new objects w bardzo łatwy sposób.

+0

Uwaga, ale do wykorzystania w przyszłości będę używał PowerMock – Xoke

+0

@edutesoy Czy możesz napisać pełny kod? Nie mogę zrozumieć twojego pomysłu. Nie widzę związku między szyderstwem konstruktora a lokalnymi kpiączkami zmiennymi. – gstackoverflow

+1

Problem z tym podejściem, jeśli używam EclEmma do pokrycia kodu jest to, że EclEmma zapewnia 0% pokrycie kodu dla MyClass, jeśli dodaję MyClass.class do @PrepareForTest zamiast rzeczywistego zasięgu kodu. Myślę, że jest to ograniczenie lub błąd w narzędziu EclEmma. Jakiś pomysł na rozwiązanie tego problemu? –

9

Nie ma mowy. Będziesz potrzebował zastrzyku zależności, czyli zamiast tworzyć instancje obj1, powinien on być dostarczony przez pewną fabrykę.

MyObjectFactory factory; 

public void setMyObjectFactory(MyObjectFactory factory) 
{ 
    this.factory = factory; 
} 

void method1() 
{ 
    MyObject obj1 = factory.get(); 
    obj1.method(); 
} 

Wtedy twoje testy wyglądałby następująco:

@Test 
public void testMethod1() throws Exception 
{ 
    MyObjectFactory factory = Mockito.mock(MyObjectFactory.class); 
    MyObject obj1 = Mockito.mock(MyObject.class); 
    Mockito.when(factory.get()).thenReturn(obj1); 

    // mock the method() 
    Mockito.when(obj1.method()).thenReturn(Boolean.FALSE); 

    SomeObject someObject = new SomeObject(); 
    someObject.setMyObjectFactory(factory); 
    someObject.method1(); 

    // do some assertions 
} 
+2

To jest to, co mam na myśli, ale to dodaje więcej niepotrzebnego kodu, bo muszę wyśmiać metodę z lokalnego obiektu zasięgu. – Xoke

+0

Która część kodu jest niepotrzebna? –

+2

Nie chcę tworzyć Factory, aby tworzyć nowe instancje myObject i ten kod jest niepotrzebny, ponieważ jest potrzebny tylko w celu sfałszowania metody zmiennej zakresu lokalnego. – Xoke

1

Można to zrobić poprzez stworzenie metody fabryki w MyObject:

class MyObject { 
    public static MyObject create() { 
     return new MyObject(); 
    } 
} 

potem kpić, że z PowerMock.

Jednakże, poprzez kpiny z metod lokalnego obiektu zasięgu, zależy to od tego, że część implementacji metody pozostanie taka sama. Więc tracisz możliwość refaktoryzacji tej części metody bez przerywania testu. Ponadto, jeśli krotność zwracają wartości w próbnym, może przejść test jednostki, ale metoda może zachowywać się nieoczekiwanie podczas korzystania z rzeczywistego obiektu.

Podsumowując, prawdopodobnie nie należy próbować tego robić. Przeciwnie, pozwalając test drive kod (aka TDD), należy dojść do rozwiązania jak:

void method1(MyObject obj1) { 
    obj1.method1(); 
} 

przechodzącą w zależności, które można łatwo drwić dla testów jednostkowych.

1

Najlepszym rozwiązaniem jest nie dotykać kodu i nie kpić z konstruktora, tak jak w tym przykładzie, aby kpić z utworzenia obiektu File wewnątrz metody. Nie zapomnij o, aby umieścić klasę, która utworzy plik w @PrepareForTest.

package hello.easymock.constructor; 

import java.io.File; 

import org.easymock.EasyMock; 
import org.junit.Assert; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.api.easymock.PowerMock; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest({File.class}) 
public class ConstructorExampleTest { 

    @Test 
    public void testMockFile() throws Exception { 

     // first, create a mock for File 
     final File fileMock = EasyMock.createMock(File.class); 
     EasyMock.expect(fileMock.getAbsolutePath()).andReturn("/my/fake/file/path"); 
     EasyMock.replay(fileMock); 

     // then return the mocked object if the constructor is invoked 
     Class<?>[] parameterTypes = new Class[] { String.class }; 
     PowerMock.expectNew(File.class, parameterTypes , EasyMock.isA(String.class)).andReturn(fileMock); 
     PowerMock.replay(File.class); 

     // try constructing a real File and check if the mock kicked in 
     final String mockedFilePath = new File("/real/path/for/file").getAbsolutePath(); 
     Assert.assertEquals("/my/fake/file/path", mockedFilePath); 
    } 

} 
24

Odpowiedź z @edutesoy punktów w dokumentacji PowerMockito i wspomina konstruktor wyśmianie jako wskazówka, ale nie wspomina, jak zastosować to do obecnego problemu w pytaniu.

Oto rozwiązanie oparte na tym.Biorąc kod z pytaniem:

public class MyClass { 
    void method1{ 
     MyObject obj1=new MyObject(); 
     obj1.method1(); 
    } 
} 

Poniższy test tworzenia makiety klasy instancji myObject poprzez przygotowanie klasy, która tworzy wystąpienie go (w tym przykładzie Wołam go MojaKlasa) z PowerMock i pozwalając PowerMockito do odgałęzienie konstruktor klasy MyObject, a potem pozwalając skrótową z MyObject instancja method1() połączenia:

@RunWith(PowerMockRunner.class) 
@PrepareForTest(MyClass.class) 
public class MyClassTest { 
    @Test 
    public void testMethod1() {  
     MyObject myObjectMock = mock(MyObject.class); 
     when(myObjectMock.method1()).thenReturn(<whatever you want to return>); 
     PowerMockito.whenNew(MyObject.class).withNoArguments().thenReturn(myObjectMock); 

     MyClass objectTested = new MyClass(); 
     objectTested.method1(); 

     ... // your assertions or verification here 
    } 
} 

Mając to Twój wewnętrzny method1() wywołanie zwróci to, co chcesz.

Jeśli lubisz jednej wkładki można uczynić kod krótszym tworząc makiety i inline skrótowe:

MyObject myObjectMock = when(mock(MyObject.class).method1()).thenReturn(<whatever you want>).getMock(); 
+1

Problem z tym podejściem, jeśli używam EclEmma do pokrycia kodu jest to, że EclEmma zapewnia 0% pokrycie kodu dla MyClass, jeśli dodaję MyClass.class do @PrepareForTest zamiast rzeczywistego zasięgu kodu. Myślę, że jest to ograniczenie lub błąd w narzędziu EclEmma. Jakiś pomysł na rozwiązanie tego problemu? –

+1

@Vidyasagar I Znalazłem ten sam problem w sonarze/Jacoco. –

Powiązane problemy