I try to Setup a mock for Update function,
public class JelentkezokService : IJelentkezokService
{
IJelentkezokRepository JelentkezokRepository { get; set; }
public Jelentkezok Update(Jelentkezok jelentkezo)
{
if (JelentkezokRepository.GetAll().Any(x => x.Id == jelentkezo.Id))
{
return JelentkezokRepository.Update(jelentkezo);
}
//The ID is not exist
else throw new Exception($"A megadott jelentkező ID nem létezik: {jelentkezo.Id}");
}
}
testing whether the function was called but it goes for the exception in the Service. Any idea?
[TestFixture]
public class JelentkezokBLTests
{
Mock<IJelentkezokRepository> JelentkezokRepositoryMock;
[Test]
public void JelentkezokUpdateMeghivva()
{
//Arrange
JelentkezokRepositoryMock = new Mock<IJelentkezokRepository>();
var input = new DA.Jelentkezok()
{
Id = 13,
Nev = "Kis Béla",
Varos = "Győr",
Utca = "Kodály Zoltán u. 15.",
SzuletesiDatum = new DateTime(1982, 11, 19),
Iranyitoszam = 9030,
Ferfi = true,
};
var mockedResult = new DA.Jelentkezok()
{
Id = 13,
Nev = "Kis Anita",
Varos = "Győr",
Utca = "Kodály Zoltán u. 15.",
SzuletesiDatum = new DateTime(1982, 11, 19),
Iranyitoszam = 9030,
Ferfi = false,
};
JelentkezokRepositoryMock.Setup(x => x.Update(input)).Returns(mockedResult);
JelentkezokService service = new JelentkezokService(JelentkezokRepositoryMock.Object);
//Act
var updateJelentkezo = service.Update(input);
//Assert
//Assert.That(input, Is.Not.Null);
JelentkezokRepositoryMock.Verify(v => v.Update(input), Times.AtLeastOnce);
}
I have the error
Message: System.Exception : A megadott jelentkező ID nem létezik: 13 //The ID is not exist.
Looks like JelentkezokRepository.GetAll() is not behaving as expected.
Assuming it returns a collection
IEnumerable<Jelentkezok> GetAll();
That may need to be setup as well.
//...
var item = new DA.Jelentkezok() {
Id = 13,
};
var all = new [] { item };
JelentkezokRepositoryMock.Setup(x => x.GetAll()).Returns(all);
//...
In order to allow the if condition to flow as expected when the test is exercised.
Related
I'm trying to write unit test using xUnit for EntityService class which is using Dapper to get data from Sqllite database. In my unit test it always returns actual values as List<Entity> [] and test fails. I'm not understanding what I am missing here.
Test Class
public class EntityServiceTests
{
private readonly IEntityService _sut;
private readonly Mock<IEntityService> _entityServiceMock;
public EntityServiceTests()
{
_entityServiceMock = new Mock<IEntityService>();
var dapperMock = new Mock<IDapperWrapper>();
_sut = new EntityService(dapperMock.Object);
}
[Fact]
public void GetEntities_ShouldReturnEntities()
{
//Arrange
var expectedEntities = new List<Entity>
{
new()
{
Id = 1,
Name = "Test",
X = 12,
Y = 14.5,
CoordId = 1
},
new()
{
Id = 2,
Name = "Test2",
X = 16,
Y = 18.5,
CoordId = 2
}
};
var query = #"SELECT ent.*, crd.x, crd.y, crd.id as CoordId
FROM entities ent
INNER JOIN coords crd ON crd.entityId = ent.Id";
_entityServiceMock.Setup(x => x.GetEntities(0)).Returns(expectedEntities);
//Act
var entities = _sut.GetEntities(0).ToList();
//Assert
Assert.Equal(expectedEntities, entities);
}
}
Service Class
public class EntityService : IEntityService
{
private readonly IDapperWrapper _dapperWrapper;
public EntityService(IDapperWrapper dapperWrapper)
{
_dapperWrapper = dapperWrapper;
}
public IEnumerable<Entity> GetEntities(int entityId)
{
var query = #"SELECT ent.*, crd.x, crd.y, crd.id as CoordId
FROM entities ent
INNER JOIN coords crd ON crd.entityId = ent.Id ";
if (entityId > 0)
{
query += " WHERE ent.id = #id";
var entities = _dapperWrapper.Query<Entity>(query, new { id = entityId });
return entities;
}
else
{
var entities = _dapperWrapper.Query<Entity>(query);
return entities;
}
}
}
Dapper Wrapper Class
public class DapperWrapper : IDapperWrapper
{
private IDbConnection Connection { get; }
public DapperWrapper()
{
Connection = new SQLiteConnection(GetConnectionString("ConnectionString"));
}
private string GetConnectionString(string name)
{
return ConfigurationManager.ConnectionStrings[name].ConnectionString;
}
public IEnumerable<T> Query<T>(string query)
{
return Connection.Query<T>(query);
}
public IEnumerable<T> Query<T>(string query, object param)
{
return Connection.Query<T>(query, param);
}
public T QuerySingle<T>(string query, object param)
{
return Connection.QuerySingle<T>(query, param);
}
}
Normally the project is working fine. but in Test it fails. I think i'm missing something very basic but crucial.
UPDATE: I'm using this code now but still getting failed result
[Fact]
public void GetEntities_Should_Return_All_Entities_If_0_Is_Provided_In_Param()
{
//Arrange
var expectedEntities = new List<Entity>
{
new()
{
Id = 1,
Name = "Test",
X = 12,
Y = 14.5,
CoordId = 1
},
new()
{
Id = 2,
Name = "Test2",
X = 16,
Y = 18.5,
CoordId = 2
}
};
var query = #"SELECT ent.*, crd.x, crd.y, crd.id as CoordId
FROM entities ent
INNER JOIN coords crd ON crd.entityId = ent.Id ";
var dapperMock = new Mock<IDapperWrapper>();
dapperMock.Setup(x => x.Query<Entity>(query)).Returns(expectedEntities);
var sut = new EntityService(dapperMock.Object);
//Act
var entities = sut.GetEntities(0);
//Assert
Assert.Equal(expectedEntities, entities);
}
I think i'm missing something very basic but crucial.
Indeed 🙂 mocking is intended to be used to mock away the dependencies from a unit to test (sut). In your case your unit to test is the EntityService and the dependency to mock away is IDapperWrapper.
But instead of only mocking the dependency, you're mocking the SUT as well with _entityServiceMock.
So you COULD try to do it like this within your test:
public class EntityServiceTests
{
[Fact]
public void GetEntities_ShouldReturnEntities()
{
//Arrange
var expectedEntities = new List<Entity>
{
new()
{
Id = 1,
Name = "Test",
X = 12,
Y = 14.5,
CoordId = 1
}
};
var query = #"SELECT ent.*, crd.x, crd.y, crd.id as CoordId
FROM entities ent
INNER JOIN coords crd ON crd.entityId = ent.Id WHERE ent.id = #id";
var dapperMock = new Mock<IDapperWrapper>();
dapperMock.Setup(x => x.Query<Entity>(query, 1)).Returns(expectedEntities.First());
var sut = new EntityService(dapperMock.Object);
//Act
var entities = sut.GetEntities(1).ToList();
//Assert
Assert.Equal(expectedEntities, entities);
}
}
But I highly discourage you from doing so because you'll end up mocking all the Dapper stuff.
Instead you better use an in-memory database (like SQLite), use a real Dapper instance. This way your tests will become much more comprehensive, shorter and business-facing. This blog post should give you a good starting point.
In short, I have two NUnit test cases in a Standard project using Moq that when I run them individually, they pass, but run separately the second one fails. Specifically, the first takes 1.9s to run, and the second fails immediately (118ms) saying the result is 0 though it should be 1.
Code (included sample setup code for orders, test code and code being tested):
[SetUp]
public void Initialize()
{
clocationData = new CalfeeLocationData();
clocationData.ApplyDefaultMockDataset();
mlocationData = new MeetingLocationData();
mlocationData.ApplyDefaultMockDataset();
mlocationLayoutData = new MeetingLocationLayoutData();
mlocationLayoutData.ApplyDefaultMockDataset();
orderData = new OrderData();
orderData.ApplyDefaultMockDataset();
orderDetailData = new OrderDetailData();
orderDetailData.ApplyDefaultMockDataset();
orderRepository = (OrderRepository)orderData.GetRepository();
}
public override void ApplyDefaultMockDataset()
{
ClearMockData();
SetDefaultOrder();
}
private void SetDefaultOrder()
{
var ord = new Order()
{
EntryId = "000-333",
GlobalId = "000-999-99999",
OrganizerGraphId = "Id",
BillingInfo = "Nada",
OtherInstructions = "No Other Complications",
MeetingLocationId = 79
};
AddMockData(ord);
}
[TestCase(true, 1)]
[TestCase(false, 1)]
public void GetAllByCreator_OneTest(bool includeDelete, int expectedCount)
{
var saveModel = CreateOrder();
orderRepository.Save(saveModel);
var foundOrder = orderRepository.GetById(saveModel.OrderId);
foundOrder.OrganizerEmail = testEmail;
orderRepository.Save(foundOrder);
var foundOrders = orderRepository.GetAllByOrganizer(saveModel.OrganizerEmail, includeDelete);
Assert.AreEqual(expectedCount, foundOrders.Count);
}
public List<Order> GetAllByOrganizer(string organizerEmail, bool getDeleted = false)
{
var baseQuery = GetDataQueryBase();
var orders = baseQuery.Where(mod => mod.OrganizerEmail == organizerEmail);
if (!getDeleted) orders = orders.Where(mod => !mod.Deleted);
return orders.OrderBy(c => c.CreatedDate).ToList();
}
I'm using the moq framework by Daniel Cazzulino, kzu Version 4.10.1.
I want to moq so i can test a particular part of functionality (below is the simplistic version of the Code i could extract)
The fluent/chain method so are designed so you can get object by an Id and include any additional information if required.
i'm having some trouble fetching the correct object when the function is calling the moq'ed method, which is currently returning the last moq'ed object which is wrong
/*My current Moq setup*/
class Program
{
static void Main(string[] args)
{
var mock = new Mock<IFluent>();
var c1 = new ClassA() { Id = 1, Records = new List<int>() { 5, 2, 1, 10 }, MetaData = new List<string>() };
var c2 = new ClassA() { Id = 2, Records = new List<int>(), MetaData = new List<string>() { "X", "Y", "Z" } };
mock.Setup(x => x.GetById(1).IncludeRecords().IncludeMetaData().Get()).Returns (c1);
mock.Setup(x => x.GetById(2).IncludeRecords().IncludeMetaData().Get()).Returns(c2);
var result = new ComputeClass().ComputeStuff(mock.Object);
Console.WriteLine(result);
Console.ReadLine();
}
}
/*Fluent interface and object returned*/
public interface IFluent
{
IFluent GetById(int id);
IFluent IncludeRecords();
IFluent IncludeMetaData();
ClassA Get();
}
public class ClassA
{
public int Id { get; set; }
public ICollection<int> Records { get; set; }
public ICollection<string> MetaData { get; set; }
}
/*the method which is doing the work*/
public class ComputeClass
{
public string ComputeStuff(IFluent fluent)
{
var ids = new List<int>() { 1, 2 };
var result = new StringBuilder();
foreach (var id in ids)
{
var resClass = fluent.GetById(id).IncludeRecords().IncludeMetaData().Get();
result.Append($"Id : {id}, Records: {resClass.Records.Count}, MetaData: {resClass.MetaData.Count}{Environment.NewLine}");
}
return result.ToString();
}
}
Current incorrect result
/*Id : 1, Records: 0, MetaData: 3
Id : 2, Records: 0, MetaData: 3*/
Expected Result
/*Id : 1, Records: 3, MetaData: 0
Id : 2, Records: 0, MetaData: 3*/
The easiest way would be to split out each setup:
var mock = new Mock<IFluent>();
var mock1 = new Mock<IFluent>();
var mock2 = new Mock<IFluent>();
mock.Setup(x => x.GetById(1)).Returns(mock1.Object);
mock1.Setup(x => x.IncludeRecords()).Returns(mock1.Object);
mock1.Setup(x => x.IncludeMetaData()).Returns(mock1.Object);
mock1.Setup(x => x.Get()).Returns(c1);
mock.Setup(x => x.GetById(2)).Returns(mock2.Object);
mock2.Setup(x => x.IncludeRecords()).Returns(mock2.Object);
mock2.Setup(x => x.IncludeMetaData()).Returns(mock2.Object);
mock2.Setup(x => x.Get()).Returns(c2);
var result = new ComputeClass().ComputeStuff(mock.Object);
You could create an extension/utility to handle this all for you if you wanted something a bit more complex, take a look at this blog post: https://www.codemunki.es/2014/11/20/mocking-a-fluent-interface-automatically-in-moq/
Just an addition to the already existing answer. For mocking fluent API there is one usefull option within the moq, it is SetReturnsDefault, it could save some mocking especially if you have huge fluent API, e.g.
var mock = new Mock<IFluent>();
var mock1 = new Mock<IFluent>();
var mock2 = new Mock<IFluent>();
mock.Setup(x => x.GetById(1)).Returns(mock1.Object);
mock1.SetReturnsDefault(mock1.Object);
mock1.Setup(x => x.Get()).Returns(a);
mock.Setup(x => x.GetById(2)).Returns(mock2.Object);
mock2.SetReturnsDefault(mock2.Object);
mock2.Setup(x => x.Get()).Returns(b);
var aa = mock.Object.IncludeMetaData().GetById(1).IncludeMetaData().Get();
var bb = mock.Object.IncludeMetaData.GetById(2).IncludeMetaData.Get();
With this approach you actually have to mock only method which differ but not the all methods from fluent API.
Hello,
I'm having trouble getting my class to call a Moq'd method. My situation is thus:
public class ResetPasswordsTask : IRefreshTimeTask
{
public long ExecutionId => 2100;
public bool Enabled => true;
public Dictionary<string, object> Params { get; set; }
public KeyValuePair<string, Type>[] RequiredParams => new[]
{
new KeyValuePair<string, Type>("targetConfigs", typeof(InMemoryConfiguration))
};
public ILogger Logger { get; set; }
internal IConfiguration SandboxConfig;
internal IPartnerService PartnerService;
internal ISalesForceBulkDataInserter DataInserter;
public void Execute()
{
SandboxConfig = (IConfiguration)Params["targetConfigs"];
PartnerService = Login.SalesforceApiLogin(true, SandboxConfig);
DataInserter = new SalesForceBulkDataInserter();
//InitialiseImapClient();
// Retrieve users
var users = TestAutomation.Salesforce.Pages.Base.User.GetUsers(PartnerService, SandboxConfig.Refresh_Usernames);
// Upsert emails
var emailUpsertResults = UpsertEmails(users, SandboxConfig.IMAP_Email);
// Hit mailbox and visit confirmation links
var activatedUsers = emailUpsertResults.Values.Where(r => r.Status == EmailResetStatusEnum.Success).Select(r => r.User).ToList();
var confirmationLinkResults = ConfirmEmailChanges(activatedUsers);
// Upsert passwords
// All the users, except those for whom email update failed
var passwordUpdateUsers = users.Except(confirmationLinkResults.Values.Where(r => !r.Success).Select(r => r.User)).ToList();
var passwordUpsertResults = UpsertPasswords(passwordUpdateUsers);
// Hit mailbox for new tokens
var completeResetResults = RetrieveTokens(passwordUpsertResults.Values.Where(r => r.Success));
var output = string.Join("\n", completeResetResults.Values.Where(c => c.Success).Select(result => string.Join("\t", new List<string> { result.User.Username, result.Password, result.SecurityToken })));
//Logger.Info(output);
Logger.Info(System.IO.Path.GetDirectoryName("."));
Logger.Info(System.Reflection.Assembly.GetExecutingAssembly().Location);
OpenSslEncryption.EncryptToFile(SandboxConfig.EncryptionPassword, "passwords.enc", output);
}
// Results are keyed by username
internal IDictionary<string, EmailResetResult> UpsertEmails(ICollection<User> users, string newEmail)
{
var results = users.ToDictionary(u => u.Username, u => new EmailResetResult(u));
Logger.Info($"Updating emails for {users.Count} users");
foreach (var user in users)
{
Logger.Info($"updating email for {user.Username} users");
var result = results[user.Username];
// Prevent upserting the profile
if (user.ProfileId != null)
{
Logger.Info("Preventing profile upsert");
user.ProfileId.SalesForceId = user.ProfileId.OriginId;
}
// If the user has had their email set to what we're setting now, they can be skipped
if (user.Email.Equals(newEmail, StringComparison.InvariantCultureIgnoreCase) && user.IsActive)
{
Logger.Info($"User {user.Username} has their email set to {newEmail}; skipping");
result.Status = EmailResetStatusEnum.Skipped;
continue;
}
// Otherwise, set the email and carry on
user.Email = newEmail;
user.IsActive = true;
// dataInserter.Upsert won't produce errors individually, and instead only log faulty upserts
try
{
DataInserter.Upsert(new List<User> { user });
Logger.Info($"Activated user {user.Username}");
result.Status = EmailResetStatusEnum.Success;
}
catch (Exception e)
{
var error = $"Failed to update the email for user {user.Username} to {newEmail}. Error details: {e}";
Logger.Error(TestAutomation.Framework.Core.Logger.Logger.FormatJson(error));
result.ErrorMessage = e.ToString();
result.Status = EmailResetStatusEnum.Failure;
}
}
return results;
}
internal IDictionary<string, Result> ConfirmEmailChanges(ICollection<User> users)
{
var results = users.ToDictionary(u => u.Username, u => new Result(u));
// Ran as a task to have a timeout
Task.Run(() => ConfirmEmailChangesTask(results, users)).Wait(TimeSpan.FromMinutes(users.Count * 5));
return results;
}
internal void ConfirmEmailChangesTask(IDictionary<string, Result> results, ICollection<User> users)
{
var remainingUsers = new HashSet<User>(users);
while (true)
{
// Wait a bit; either for the emails to come in, or to give the webserver breathing room
Thread.Sleep(new TimeSpan(0, 0, 15));
Logger.Info($"Opening mailbox for {SandboxConfig.IMAP_Email}");
using (var imapClient = CreateImapClient())
{
var messages = imapClient.SearchMessages(SearchQuery.NotSeen.And(SearchQuery.DeliveredAfter(DateTime.Now.AddHours(-1))));
Logger.Info($"Found {messages.Count} messages");
var remainingUsersCopy = new HashSet<User>(remainingUsers);
Logger.Info($"Attempting to confirm emails for {remainingUsers.Count} users");
foreach (var user in remainingUsersCopy)
{
Logger.Info("Attempting to confirm email change for " + user.Username);
foreach (var message in messages.Where(m => m.MimeMessage.TextBody.Contains(user.Username) && m.MimeMessage.Subject.Contains("Sandbox: Finish changing your Salesforce")))
{
Logger.Info("Message found");
var confirmLink = GetEmailConfirmationLink(message);
if (confirmLink == null) continue;
// Visit the URL
var request = WebRequest.Create(confirmLink);
request.Timeout = (int)TimeSpan.FromSeconds(20).TotalMilliseconds;
var result = results[user.Username];
try
{
using (var response = (HttpWebResponse)request.GetResponse())
{
var statusCode = response.StatusCode;
if (statusCode != HttpStatusCode.OK)
{
var error = $"Failed to load the email change confirmation link: {confirmLink}. HTTP Response: ({statusCode})";
Logger.Error(TestAutomation.Framework.Core.Logger.Logger.FormatJson(error));
result.Success = false;
result.ErrorMessage = error;
}
}
}
catch (WebException e)
{
Logger.Error($"Request failed: {e.Message}\nWill retry later");
continue;
}
result.Success = true;
remainingUsers.Remove(user);
imapClient.MarkAsRead(message);
//Break down mailbox checks
Thread.Sleep(new TimeSpan(0, 0, 1));
}
}
}
if (!remainingUsers.Any())
break;
}
}
#region MailboxInteraction
internal static string GetEmailConfirmationLink(Message message)
{
// Extract confirmation URL
var confirmLinkMatch = Regex.Match(message.MimeMessage.TextBody, #"([a-z]+:\/\/.*\.salesforce\.com\/\S*)");
return !confirmLinkMatch.Success ? null : confirmLinkMatch.Groups[1].Value;
}
internal static string GetSecurityToken(Message message)
{
var tokenMatch = Regex.Match(message.MimeMessage.TextBody, #"Security token \(case-sensitive\): (?<token>\w+)");
return !tokenMatch.Success ? null : tokenMatch.Groups[1].Value;
}
internal virtual IMailClient CreateImapClient()
{
return new IMAPClient(SandboxConfig.IMAP_Username, SandboxConfig.IMAP_Password, SandboxConfig.IMAP_URL);
}
#endregion
}
Test class:
[TestFixture]
public class WhenResettingUserPasswords
{
private const string ConfirmationLink = "test://testdomain.salesforce.com/test/";
[OneTimeSetUp]
public void WebRequestSetup()
{
WebRequest.RegisterPrefix("test", TestableWebRequestCreateFactory.GetFactory());
var uri = new Uri("test://testdomain.salesforce.com/test/");
var expectedRequest = new TestableWebRequest(uri);
expectedRequest.EnqueueResponse(HttpStatusCode.OK, "Success", "Even more success!", false);
TestableWebRequestCreateFactory.GetFactory().AddRequest(expectedRequest);
}
private static SetupBag Setup()
{
var bag = new SetupBag
{
Logger = new InMemoryLogger(),
EmailConfirmationLink = ConfirmationLink,
SecurityToken = "TheSecurityToken",
Environment = "EnvName",
EnvironmentUrl = "http://aaa.bbb.ccc/",
User = new User
{
IsActive = false,
Username = "joe.bloggs#company.com",
Email = "joe.bloggs=company.com#example.com",
OriginId = "ABCDEFGHIJKLMNO"
}
};
var task = new Mock<Tasks.ResetPasswordsTask>(MockBehavior.Strict) { CallBase = true };
task.Object.Logger = bag.Logger;
var confirmMessage = new Message
{
UID = new UniqueId(0),
MimeMessage = new MimeMessage
{
Subject = "Sandbox: Finish changing your Salesforce",
Body = new TextPart("plain") { Text = "Confirm email change for joe.bloggs#company.com: " + bag.EmailConfirmationLink }
}
};
var tokenMessage = new Message
{
UID = new UniqueId(1),
MimeMessage = new MimeMessage
{
Subject = "Sandbox: Your new Salesforce security token",
Body = new TextPart("plain") { Text = "New security token for joe.bloggs#company.com: " + bag.SecurityToken }
}
};
var mailClientMock = new Mock<IMailClient>(MockBehavior.Strict);
mailClientMock.Setup(m => m.SearchMessages(It.IsAny<SearchQuery>())).Returns(new List<Message> { confirmMessage, tokenMessage });
task.Setup(t => t.CreateImapClient()).Returns(() => mailClientMock.Object);
var dataInserterMock = new Mock<ISalesForceBulkDataInserter>();
dataInserterMock.Setup(m => m.Upsert(It.IsAny<List<User>>(), false));
var config = new InMemoryConfiguration
{
IMAP_Email = "test.email#company.com"
};
task.Object.SandboxConfig = config;
bag.Task = task;
return bag;
}
[Test]
public void UpsertEmailsTest()
{
var bag = Setup();
var task = bag.Task;
var output = task.Object.ConfirmEmailChanges(new[] { bag.User });
Assert.IsTrue(output.ContainsKey(bag.User.Username));
Assert.IsTrue(output[bag.User.Username].Success);
Assert.IsEmpty(output[bag.User.Username].ErrorMessage);
Assert.AreEqual(task.Object.SandboxConfig.IMAP_Email, output[bag.User.Username].User.Username);
}
}
Now, the result is that calling task.Object.ConfirmEmailChanges() raises an exception about arguments to new IMAPClient() being null, which should not have been called at all. I could not find anything obviously wrong, but that might just be because I'm not familiar enough with Moq or the way my codebase does testing.
Yes, I know I'm mocking a class I want to test. I know it's a bad idea, and I'm aiming for a redesign. I cannot inject IMailClient as a dependency because it needs to be instantiated anew frequently. I have also seen this sort of technique used in our codebase, and it seemed to work.
If you are mocking a concrete class and not an interface then you must make the method you want to mock virtual.
Edit: in your new code the method is also marked as internal. See this question.
You need to declare your method as virtual or Moq is unable to override it. C# is not like Java - only members that are specifically marked are able to be overridden.
EDIT
The code you've posted should work - here is a Linqpad MVCE I generated based on your code, demonstrating that it works correctly. Therefore, you will need to post your actual code, as it has a bug in it.
void Main()
{
// Arrange
var foo = new Mock<Foo> { CallBase = true };
var bar = new Mock<IBar>();
bar.Setup(b => b.Value).Returns(2);
// setup an IBar mock
foo.Setup(f => f.CreateBar()).Returns(bar.Object);
// Act
var results = foo.Object.DoStuff();
results.Dump(); // Prints "2"
}
public class Foo
{
public int DoStuff()
{
var bar = CreateBar();
return bar.Value;
}
public virtual IBar CreateBar()
{
return new RealBar();
}
}
public interface IBar
{
int Value { get;}
}
public class RealBar : IBar
{
public int Value
{
get { return 1; }
}
}
public CommandModule(ICommandFetcher fetcher,ICommandBus commandBus)
{
Post["/"] = parameters =>
{
var commandRequest = this.Bind<MessageEnvelope>();
var command = fetcher.FetchFrom(commandRequest);
commandBus.Send((ICommand)command, commandRequest.MetaData);
return HttpStatusCode.OK;
};
}
error-->Unable to cast object of type 'Castle.Proxies.ObjectProxy_2' to type 'Vetserve.Messages.Shared.ICommand'.
in commandBus.Send((ICommand)command, commandRequest.MetaData); line
Hi
when i try to test using nunit test this method has previous error how can i fix it
this is my test class
[Test]
public void whern_reseiving_command_it_sent_to_the_command_bus()
{
var rCommand = new DummyCommand() {SomeProp = 2};
var serializedCommand = JsonConvert.SerializeObject(rCommand);
var envelope = new MessageEnvelope()
{
MetaData = new MetaData() {MessageType = "DummyCommand", MessageTypeVersion = 1},
MessageData = serializedCommand
};
var fakeCommand = A.Fake<ICommandBus>();
var fakeCxxommand = A.Fake<ICommandFetcher>();
var browser = new Browser(with =>
{
with.Module<CommandModule>();
with.Dependency<ICommandBus>(fakeCommand);
with.Dependency<ICommandFetcher>(fakeCxxommand);
});
var result = browser.Post("/", with =>
{
with.HttpRequest();
with.JsonBody(envelope);
});
A.CallTo(() => fakeCommand.Send(A<ICommand>.Ignored , envelope.MetaData)).MustHaveHappened();
// A.CallTo(() => fakeCommand.Send(A<ICommand>.Ignored, A<MetaData>._)).MustHaveHappened();
}
[Test]
public void whern_reseiving_command_it_sent_to_the_command_bus()
{
var rCommand = new DummyCommand() {SomeProp = 2};
var serializedCommand = JsonConvert.SerializeObject(rCommand);
var envelope = new MessageEnvelope()
{
MetaData = new MetaData{MessageType = "DummyCommand", MessageTypeVersion = 1},
MessageData = serializedCommand
};
var fakeCommand = A.Fake<ICommandBus>();
var fakeCommandFetcher = A.Fake<ICommandFetcher>();
A.CallTo(()=> fakeCommandFetcher.FetchFrom(A<MessageEnvelope>._)).Returns(rCommand);
var browser = new Browser(with =>
{
with.Module<CommandModule>();
with.Dependency<ICommandBus>(fakeCommand);
with.Dependency<ICommandFetcher>(fakeCommandFetcher);
});
var result = browser.Post("/", with =>
{
with.HttpRequest();
with.JsonBody(envelope);
});
A.CallTo(() => fakeCommand.Send(rCommand,A<MetaData>.That.Matches(m =>m.ContextInfo == envelope.MetaData.ContextInfo && m.MessageType == envelope.MetaData.MessageType))).MustHaveHappened();
}
this is my new test method it work fine.
previous error occur due to wrong type of fetch from method
public interface ICommandFetcher
{
Object FetchFrom(MessageEnvelope messageEnvelope);
}
i changed it into
public interface ICommandFetcher
{
ICommand FetchFrom(MessageEnvelope messageEnvelope);
}
now its working.