Ваш модульный тест контроллера не должен использовать ваш CustomMembershipProvider
или стандартный поставщик SQL. При выполнении модульного теста вы должны использовать Stub / Fake, чтобы иметь полный контроль над тем, что он возвращает. Если в тесте вы используете реального провайдера, он больше не является модульным тестом, это интеграционный тест.
Чтобы достичь тестируемости юнитов, вам нужно определить провайдера подделки, либо с помощью фреймворка Mocking, либо вручную подбрасывая фальшивку с «консервированными» результатами. Подделка может выглядеть примерно так:
public class FakeMembershipProvider : MembershipProvider
{
public MembershipCreateStatus CreateStatus = MembershipCreateStatus.Success;
public void CreateUser((string username, string password, string email,
string passwordQuestion, string passwordAnswer, bool isApproved,
object providerUserKey, out MembershipCreateStatus status)
{
status = CreateStatus;
}
...
}
Пусть контроллер принимает провайдера в качестве аргумента ctor
public class AccountController
{
private readonly MembershipProvider _membershipProvider;
public AccountController(MembershipProvider membershipProvider)
{
_membershipProvider = membershipProvider;
}
public ActionResult Register(RegistrationModel model)
{
MembershipCreateStatus result;
_membershipProvider.CreateUser(model.Email, model.Password, ..., out result);
return View(/*Make this depend on the result*/);
}
}
В модульном тесте вы хотите настроить подделку в соответствии с тем, что вы хотите проверить, и вы можете утверждать результат, который вы ожидаете для каждого результата регистрации:
[Test]
void Should_display_success_view_when_user_successfully_created()
{
var membershipProvider = new FakeMembershipProvider();
membershipProvider.CreateStatus = MembershipCreateStatus.Success;
var controller = new AccountController(membershipProvider);
var model = new RegistrationModel();
var result = controller.Register(model) as ViewResult;
Assert.That(result.Name, Is.EqualTo("ExpectedViewName"));
}
Поскольку MemberShipProvider довольно велик, и вы, вероятно, не собираетесь использовать все его, разумно использовать подход @SteveWilkes, заключающийся в обертывании класса Membership, чтобы создать меньший и более целевой интерфейс. Кроме того, насмешливый фреймворк сэкономит вам много работы. Чтобы связать ваш контроллер с новой зависимостью, вы должны создать новую ControllerFactory.