2014-04-24 8 views
6

Sto utilizzando SignalR in un progetto MVC5. Sto effettuando chiamate all'interno del controller in questo modo:Come devo simulare SignalR HubContext nel controller per il test dell'unità?

private Microsoft.AspNet.SignalR.IHubContext blogHubContext = Microsoft.AspNet.SignalR.GlobalHost.ConnectionManager.GetHubContext<BlogHub>(); 
blogHubContext.Clients.All.addNewBlogToPage(RenderPartialViewToString("Blog", model)); 

Sto tentando di testare le azioni all'interno di questo controller. I test di unità funzionavano bene fino a quando non ho aggiunto la funzionalità SignalR. Ora sto cercando di capire come deridere l'HubContext. Ho 2 possibilità.

  1. ho configurato l'hub nel costruttore in modo da avere qualcosa di simile a quanto segue:

    private Microsoft.AspNet.SignalR.IHubContext blogHubContext; 
    public BlogController(Microsoft.AspNet.SignalR.IHubContext topicHub = null){ 
        blogHubContext = (blogHub != null) ? blogHub : Microsoft.AspNet.SignalR.GlobalHost.ConnectionManager.GetHubContext<BlogHub>(); 
    } 
    

    Allora posso in qualche modo prendere in giro il HubContext e inviarlo tramite al controller quando creo nel unità test. Finora ho solo questo però:

    Mock<IHubContext> blogHub = new Mock<IHubContext>(); 
    

    (Nota:. Ho semplificato tutto per concentrarsi sul solo il lato SignalR delle cose ci sono anche repository usati nella controllore ecc)

  2. In alternativa, ho ho pensato di creare un'altra classe per avvolgere l'hub e quindi chiamare semplicemente le funzioni da questa per effettuare chiamate all'hub. Questo mi sembra molto più facile da prendere in giro per i miei test unitari, ma non sono sicuro che sia una buona idea.

Direzione apprezzata. O sono entrambe le vie accettabili? Grazie.

+0

preferisco la prima opzione in quanto non è necessario un altro strato supplementare di classe wrapper, che non aggiunge alcuna funzionalità. –

+0

@ AD.Net Grazie. In quel caso, qualsiasi idea su come posso fare il giro dell'hub per la funzionalità che sto usando. Ho faticato a capire come farlo, cosa che mi ha portato a pensare alla seconda opzione. – AndrewPolland

+0

Hai familiarità con la derisione in generale? Prendere in giro un hub signalr sembra come se fosse quasi lo stesso che deride qualsiasi altra cosa. –

risposta

1

Aggiornamento, si prega di consultare questo codice, sto basando questo fuori il modello MVC predefinito. Non c'è bisogno di una classe wrapper.

public class HomeController : Controller 
{ 
    private readonly IHomeHub _hub; 

    public HomeController(IHomeHub hub) 
    { 
     _hub = hub; 
    } 

    public ActionResult Index() 
    { 
     _hub.Hello(); 
     return View(); 
    } 
} 

public interface IHomeHub 
{ 
    void Hello(); 
} 

public class HomeHub : Hub, IHomeHub 
{ 
    public void Hello() 
    { 
     Clients.All.hello(); 
    } 
} 

per i test unitari:

[TestMethod] 
public void Index() 
{ 
    var mockHub = new Mock<IHomeHub>(); 
    // Arrange 
    HomeController controller = new HomeController(mockHub.Object); 

    // Act 
    ViewResult result = controller.Index() as ViewResult; 

    // Assert 
    Assert.IsNotNull(result); 
    mockHub.Verify(h=>h.Hello(), Times.Once); 
} 
+0

Questo sembrava davvero buono. Ma non riesco a farlo funzionare solo perché è in grado di chiamare una funzione dall'hub (all'interno del controller) se è statica, cosa che non può essere se implementata da un'interfaccia. Quindi la mia comprensione comunque. – AndrewPolland

+0

scusa non è chiaro, il metodo Hello non è statico sulla classe Hub e puoi chiamarlo dal controller. –

+0

Scusa, parte del problema era la mia fine. Statico non è necessario come stavo pensando. Tuttavia, quando si chiama il metodo Hello dal controller, il client non può essere chiamato come tu hai. Produce il seguente errore: l'utilizzo di un'istanza Hub non creata da HubPipeline non è supportato. – AndrewPolland

Problemi correlati