Я не использовал Entity Framework, и я не уверен на 100%, что знаю все, что здесь происходит, но то, что вам нужно сделать, - это поместить оболочку в код вашей структуры Entity Framework, который имеет интерфейс, а затем использовать фальшивый фреймворк, притворяясь, что вы вызываете базу данных, а на самом деле это не так. Я дам вам общую идею, но вам придется применить ее к Entity Framework, поскольку я не знаю специфики.
public interface IShareSpaceGateway {
IEnumerable<ShareSpace> GetSharedSpaces(string spaceToShare, string emailToShareIt);
}
public class ShareSpaceGatewayEF: IShareSpaceGateway
{
// MySpacesShared should be included up here, not sure what type it is
public IEnumerable<ShareSpace> GetSharedSpaces(string spaceToShare, string emailToShareIt)
{
if (!this.MySpacesShared.IsLoaded)
this.MySpacesShared.Load();
return this.MySpacesShared.Any(s => (s.EmailAddress == emailToShareIt)
& (s.SpaceName == spaceToShare));
}
}
Вы можете поместить любой метод, который вам нужен, в ISharedSpaceGateway, который имеет смысл. Идея состоит в том, чтобы уменьшить количество повторений кода.
Теперь вы хотите иметь возможность внедрить вашу новую зависимость на IShareSpaceGateway. Лучший способ работы с внедрением зависимостей - использовать DI-контейнер, такой как Castle Windsor, Structure Map, Ninject или Unity. Я предполагаю, что ваш код может выглядеть здесь:
public class Account
{
private ISharedSpaceGateway _sharedSpaceGateway;
public Account(ISharedSpaceGateway sharedSpaceGateway)
{
_sharedSpaceGateway = sharedSpaceGateway;
}
public int ID { get; set; }
public string Key1 { get; set; }
public string Key2 { get; set; }
public string AccountName { get; set; }
public void ShareSpace(string spaceToShare,string emailToShareIt)
{
SharedSpace shareSpace = new SharedSpace();
shareSpace.InvitationCode = Guid.NewGuid().ToString("N");
shareSpace.DateSharedStarted = DateTime.Now;
shareSpace.Expiration = DateTime.Now.AddYears(DefaultShareExpirationInYears);
shareSpace.Active = true;
shareSpace.SpaceName = spaceToShare;
shareSpace.EmailAddress = emailToShareIt;
var sharedSpaces = sharedSpaceGateway.GetSharedSpaces(spaceToShare, emailToShareIt);
if(sharedSpaces.Count() > 0)
throw new InvalidOperationException("Cannot share the a space with a user twice.");
this.MySpacesShared.Add(shareSpace);
}
}
Теперь, в вашем модульном тесте, вы хотите использовать макет, такой как Moq или RhinoMocks, для настройки вашего теста. В своем тесте вы не хотите использовать вашу реальную реализацию SharedSpaceGateway, вы хотите передать поддельную. В этом примере используется RhinoMocks
public class TestFixture{
private ISharedSpaceGateway gateway;
[TestInitialize()]
public void MyTestInitialize()
{
gateway = MockRepository.CreateMock<ISharedSpaceGateway>();
gateway.Expect(g => g.GetSharedSpaces("spaceName", "user1@domain.com"))
.Return(new SharedSpace()); // whatever you want to return from the fake call
user = new User()
{
Active = true,
Name = "Main User",
UserID = 1,
EmailAddress = "user1@userdomain.com",
OpenID = Guid.NewGuid().ToString()
};
account = new Account(gateway) // inject the fake object
{
Key1 = "test1",
Key2 = "test2",
AccountName = "Brief Account Description",
ID = 1,
Owner = user
};
}
[TestMethod]
public void Cannot_Share_SameSpace_with_same_userEmail_Twice()
{
account.ShareSpace("spaceName", "user1@domain.com");
try
{
account.ShareSpace("spaceName", "user1@domain.com");
Assert.Fail("Should throw exception when same space is shared with same user.");
}
catch (InvalidOperationException)
{ /* Expected */ }
Assert.AreEqual(1, account.MySpacesShared.Count);
Assert.AreSame(null, account.MySpacesShared.First().InvitedUser);
gateway.VerifyAllExpectations();
}
Существует множество аспектов использования DI-фреймворков и макетов, но эти концепции делают ваш код намного более тестируемым.