2017-06-21 2 views
1

Je cette classe, où je suis en train de se moquer de la création d'objets pour UrlWrapper.classMocking nouvelle() à l'aide Runnable powerMockito

public class WorkerClass { 
    private final String url; 

    public WorkerClass(String url) { 
    this.url = url; 
    } 

    void performOperation(Executor executor) throws IOException { 
    Runnable runnable = new Runnable() { 
     @Override 
     public void run() { 
      UrlWrapper urlWrapper = null; 
      try { 
       urlWrapper = new UrlWrapper(url); 
       HttpURLConnection connection = (HttpURLConnection) urlWrapper.openConnection(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

     } 
    }; 
    executor.execute(runnable); 
    } 
} 

C'est le code de test que j'ai essayé

@RunWith(PowerMockRunner.class) 
@PrepareForTest({UrlWrapper.class, WorkerClass.class}) 
public class TestClass { 
    @Before 
    public void init() throws Exception { 
    UrlWrapper urlWrapper = Mockito.mock(UrlWrapper.class); 
    PowerMockito.whenNew(UrlWrapper.class) 
       .withArguments(Mockito.anyString()) 
       .thenReturn(urlWrapper); 
    } 

    @Test 
    public void test() throws IOException { 
    Executor executor = new Executor() { 
     @Override 
     public void execute(Runnable command) { 
      command.run(); 
     } 
    }; 

    WorkerClass workerClass = new WorkerClass(""); 
    workerClass.performOperation(executor); 
    } 
} 

Mais ce n'est pas moqué. La simulation fonctionne bien sans Runnable.

Que manque-t-il ici?

+0

Question intéressante; mon vote pour ça. Bien que ma réponse vous dise de faire quelque chose de complètement différent. J'espère que vous trouverez la réponse au moins utile, maintenant que vous avez atteint ce niveau ;-) – GhostCat

Répondre

1

Votre problème est ici:

@PrepareForTest({UrlWrapper.class, WorkerClass.class 

Et là:

Runnable runnable = new Runnable() { 

Chose est: vous n'êtes pas appeler nouvelle au sein de la catégorie des travailleurs . Vous créez une anonyme classe interne de Worker (cette instanciation Runnable) - et là vous faites l'appel nouveau.

Je vois deux options:

  • Bien sûr, cette classe interne anonyme ... a en fait un nom de classe. Alors, peut-être vous êtes en mesure d'utiliser le « mutilée » nom de la classe, et passer que pour @PrepareForTest
  • Évitez d'appeler nouveau cette façon

Je doute plutôt que vous obtenez la première option de travailler . Même si cela fonctionne, ce serait probablement une solution de contournement très sale.

Le réel réponse est: apprendre à écrire le code testable , par exemple en regardant ces videos. Votre problème réel est cet appel à nouveau. Une solution: créer une usine qui vous donne des objets URL; puis utilisez l'injection de dépendance pour acquérir cette fabrique dans votre runnable.

Cette usine peut être raillée sans PowerMock (ito) ... et tout à coup, votre conception entière est améliorée; en même temps, il devient plus facile à tester.