2016-04-04 8 views
0

Ich kann es schaffen, aber ich möchte wissen, was die beste Praxis ist und warum. Ich habe einen Controller, ein Model und ein Repository und möchte nun den Controller testen. Ich schreibe gerade einen einfachen Test, um sicherzustellen, dass die richtige Ansicht zurückgegeben wird.Unit Testen eines Controllers - Wie handle ich die Verbindungszeichenfolge?

Dies ist meine Methode in der Steuerung:

public ActionResult Selections(SelectionsViewModel model) 
    { 
     for (int i = 0; i < model.Sends.Count; i++) 
     { 
      Send send = new Send(new SendService(new Database().GetConnectionString())) 
      { 
       SendID = model.Sends[i].SendID, 
       Title = model.Sends[i].Title, 
       Subject = model.Sends[i].Subject, 
       SentDate = model.Sends[i].SentDate, 
       TimesViewed = model.Sends[i].TimesViewed, 
       Include = model.Sends[i].Include, 
       Exclude = model.Sends[i].Exclude 
      }; 
      send.UpdateIncludeExclude(); 
     } 

     return View(model); 
    } 

Hier ist mein GetConnectionString() -Methode in der Datenbank-Klasse, die über meinen SendService Konstruktor gesendet wird.

public string GetConnectionString() 
    { 
     return System.Configuration.ConfigurationManager.ConnectionStrings["DEVConnectionString"].ToString(); 
    } 

Und schließlich mein Unit-Test:

[Test] 
    public void TestAssignmentSelections() 
    { 
     var obj = new AssignmentController(); 

     var actResult = obj.Selections() as ViewResult; 

     NUnit.Framework.Assert.That(actResult.ViewName, Is.EqualTo("Selections")); 
    } 

nun nicht mein Gerät zu testen, und ich warum. Mein Komponententestprojekt hat keinen Zugriff auf die web.config des Projekts, das ich teste, wo sich meine Verbindungszeichenfolge befindet.

Ich habe einige Nachforschungen gemacht, und anscheinend nur eine web.config zu meinem Unit-Test-Projekt hinzufügen und setzen die Verbindungszeichenfolge dort auch wird es funktionieren .. aber das scheint wie ein Hack.

Was ist der beste Weg, um darüber zu gehen? Gibt es eine andere Möglichkeit, meinen Code zu schreiben, um dies zu berücksichtigen?

Antwort

3

Sie möchten Ihre Controller-Einheit testbar machen? Tu das nicht.

new SendService(

Mit diesem Code werden hartzucodieren Sie Ihre konkrete Service-Implementierung & Ihre Implementierung Zugangscode-Daten. In Ihrem Komponententest sollten Sie nicht wirklich auf die Daten aus Ihrer Datenbank zugreifen. Stattdessen sollten Sie eine simulierte Datenzugriffsimplementierung bereitstellen.

Hier kommt Schnittstellen, müssen Sie eine Schnittstelle für Ihre SendService erstellen.

public interface ISendService 
{ 
    void SomeMethod(); 
} 

jetzt Ihre SendService wird eine konkrete Implementierung dieser Schnittstelle sein

public class SendService : ISendService 
{ 
    public void SomeMethod() 
    { 
    // Do something 
    } 
} 

Jetzt aktualisieren Sie Ihren Controller einen Konstruktor haben, wo wir eine Implementierung von ISendService injizieren.

public class YourController : Controller 
{ 
    private ISendService sendService; 
    public YourController(ISendService sendService) 
    { 
    this.sendService = sendService; 
    }  
    public ActionResult YourActionMethod() 
    { 
    // use this.sendService.SomeMethod(); 
    } 
} 

Und Sie können einige Dependency Injection-Frameworks verwenden, um die MVC-Framework zu erzählen, die Implementierung der Schnittstelle zu verwenden, wenn der Code ausgeführt wird. Wenn Sie MVC6 verwenden, verfügt es über einen integrierten Provider für die Abhängigkeitsinjektion, den Sie verwenden können. Gehen Sie also zu Ihrer Startup Klasse und in Ihrer ConfigureServices Methode können Sie eine Schnittstelle zu einer konkreten Implementierung zuordnen.

public class Startup 
{ 
    public void ConfigureServices(IServiceCollection services) 
    { 
    services.AddTransient<ISendService, SendService>(); 
    } 
} 

Wenn Sie in einer früheren Version von MVC sind, können Sie DI-Frameworks wie Unity, Ninject betrachten usw. Sie können für Ihren Datenzugriff den gleichen Ansatz tun später/Service-Schichten. Dh: Erstellen Sie eine Schnittstelle für den Datenzugriff und injizieren Sie diese an Ihren SendService.

public Interface IDataAccess 
{ 
    string GetName(int id); 
} 

und eine Implementierung der Zugangscode, spezifische Daten verwendet/ORM

public class EFDataAccess : IDataAccess 
{ 
    public string GetName(int id) 
    { 
    // return a string from db using EF 
    } 
} 

So, jetzt der Service-Klasse wird

public class SendService : ISendService 
{ 
    private IDataAccess dataAccess; 
    public SendService(IDataAccess dataAccess) 
    { 
    this.dataAccess=dataAccess; 
    } 
    // to do : Implement methods of your ISendService interface. 
    // you may use this.dataAccess in those methods as needed. 
} 

In Komponententests sein, Sie ein Modell erstellen Implementierung Ihrer Schnittstellen, die statische Daten zurückgeben, anstatt auf die Datenbank zuzugreifen.

Zum Beispiel, wenn Sie Moq Mock Framework verwenden, können Sie dies tun.

var m = new Mock<IDataAccess>(); 
var m.Setup(s=>s.GetName(It.IsAny<int>())).Returns("Test"); 
var s = new SendService(m); 
var result= s.SomeMethod(); 
+0

Dies war hilfreich, ich denke, ich habe einige Änderungen zu machen. Vielen Dank. – halterdev

Verwandte Themen