Test method with param Action<T> with Nunit and Moq c# - c#

I'm using c#, Nunit and Moq and I want to test a method like the Remove() method, that call another method with an Action<> parameter.
public class Db
{
private readonly IMessageWrapper _messageWrapper;
private readonly IProvider _provider;
public Db(IMessageWrapper messageWrapper, IProvider provider)
{
_messageWrapper = messageWrapper;
_provider = provider;
}
public void Remove()
{
Execute(transaction =>
{
// Do something
// method to verify with unit test
_messageWrapper.SendData();
});
}
private void Execute(Action<SqlTransaction> action)
{
_provider.ExecuteAction(action);
}
}
I'd like to do something like:
public class DbTest
{
[Test]
public void Remove_Should_SendData()
{
//... create IMessageWrapper mock and IProvider mock...
var db = new Db(messageWrapperMock.Object, provider.Object);
provider.Setup(p => p.ExecuteAction(It.IsAny<Action<SqlTransaction>>));
db.Remove();
messageWrapperMock.Verify(m => m.SendData(), Times.Once());
}
}
But it doesn't work. The unit test doesn't reach the _messageWrapper.SendData();
Thanks for the help

When you setup without any code - that method does nothing, but you need it to call your action.
Try this:
provider.Setup(p => p.ExecuteAction(It.IsAny<Action<SqlTransaction>>()))
.Callback<Action<SqlTransaction>>(c => c(null));

Related

Get an error when verify the mock test in asp dot net core

private Mock<Icache<string>> _mockobj;
[TestInitialize]
public void Initialize()
{
_mockobj = new Mock<Icache<string>>();
}
[TestMethod]
public async Task methodName()
{
_mockobj.Setup(x => x.get("keyname", out id)).Returns(true);
_mockobj.Verify(x => x.get("keyname", out id), Times.Once());
}
Got an error on the verify statement the error is
Evaluation of method System.Linq.Expressions.Expression.Call requires calling method System.RuntimeType.get_IsCollectible
, which cannot be called in this context.
For the sake of brevity let's suppose we have the following stuffs:
public interface ICache<T>
{
void Get(string key, out T value);
}
class SystemUnderTest
{
private readonly ICache<string> cache;
public SystemUnderTest(ICache<string> cache)
=> this.cache = cache;
public void MethodUnderTest()
=> cache.Get("key", out var _);
}
So, the SystemUnderTest (SUT) class receives an ICache instance via constructor and uses it inside its MethodUnderTest.
Then your should look something like this:
//Arrange
var cacheMock = new Mock<ICache<string>>();
var expectedOutValue = "value";
cacheMock.Setup(c => c.Get("key", out expectedOutValue));
//Act
var sut = new SUT(cacheMock.Object);
sut.MethodUnderTest();
//Assert
cacheMock.Verify(c => c.Get("key", out expectedOutValue));
In the Arrange phase we setup the mock
In the Act phase we connect the mock and the SUT, then we call the method which uses the mock
Finally in the Assert phase we verify the usage of the mock

How to set a Moq value in Constructor C# xunit

I have a function which contains validation that check whether a variable value is null or not. I want to test that class method using xunit test. But due to this validation, I failed to call the Unit Test.
Class
public interface ICountry<CountryModel>
{
Task ProcessCall(IList<string> countryCodes);
}
public class CallOptions
{
public string Name { get; set; }
}
public class Country<CountryModel> : ICountry<CountryModel>
{
private readonly CallOptions _options;
private readonly Irepo _repo;
public Country(IOptions<CountryModel> options,Irepo repo)
{ _repo= repo
_options = options.Value;
if (string.IsNullOrWhiteSpace(_options.Name))
{
throw new ArgumentException("Missing name");
}
}
public async Task ProcessCall(IList<string> Codes)
{
_repo.set(Codes);
}
Unit Test
public class ProcessorTests
{
private Mock<Irepo> _RepositoryMock;
private Mock<IOptions<CallOptions>> options;
public ProcessorTests()
{
_RepositoryMock = new Mock<Irepo>();
options = new Mock<IOptions<CallOptions>>();
options.SetReturnsDefault("test");
}
private Country<CountryModel> CreateSut()
{
return new Country<CountryModel>(_RepositoryMock.Object, _options.Object);
}
[Fact]
public async Task ShouldCheck()
{
GetRepoMock();
await CreateSut().ProcessCall(new string[] { "TEST" });
_RepositoryMock.Verify(x => x.set(It.IsAny<List<string>>()), Times.Once);
}
private void GetRepoMock()
{
_RepositoryMock
.Setup(m => m.set(It.IsAny<List<string>>())
.ReturnsAsync(new Response<Code>(false, null, Enumerable.Empty<Code>()));
}
But when the unit test executes, the value of _options.Name is empty and failed the test while called the Country method.
Any idea regarding this?

C# UnitTest void static method

I'm trying to make an unit test for a logger in an application.
For example I need to test the method Logger.info("some message"), but this method is static and return void.
Searching on Google I understand that I have to use Moq but am unable to implement that on the UnitTest class.
The Logger constructor does not have an argument and in x.Debug I have an error that says that I can't access
from instance reference.
Is there a way to implement UnitTest without editing the production code?
[TestClass()]
public class LoggerTests
{
[TestMethod()]
public void DebugTest()
{
var mock = new Mock<Logger>();
mock.Setup(x => x.Debug(It.IsAny<string>());
new Logger(mock.Object).AddLog("testing");
mock.VerifyAll;
}
}
Program.cs
private static void ConfigureLogger()
{
Logger.AddLog(new NLogAppender());
Logger.Level = TraceLevel.Verbose;
Logger.Info("Configured Logger");
}
Logger.cs
public class Logger
{
public static readonly List<IAppender> loggings = new List<IAppender>();
public static void AddLog(IAppender appender)
{
loggings.Add(appender);
}
public static TraceLevel Level { get; set; }
static Logger()
{
Level = TraceLevel.Verbose;
}
public static void Info(string message)
{
LogMessage(message);
}
}
NlogAppender.cs
public class NLogAppender : IAppender
{
public NLog.Logger logger;
public NLogAppender()
{
logger = LogManager.GetLogger(nameof(NLogAppender));
}
public void AddLog(string str)
{
}
}
IAppender.cs
public interface IAppender
{
void AddLog(string str);
}
You can't mock a static class, and you shouldn't mock the class/system under test.
Add a mock appender to the logger:
// Arrange
var logString = "test-info"
var appenderMock = new Mock<IAppender>();
appenderMock.Setup(a => a.AddLog(logString));
Logger.AddLog(appenderMock.Object);
// Act
Logger.Info(logString);
// Assert
// TODO: exactly once
appenderMock.VerifyAll();
Note this static class may persist data between tests causing unexpected results, consult your test framework for configuring this.
Apart from that, you usually don't want to roll your own logging infrastructure, there's lots of things you can do wrong and why reinvent the wheel? Plenty of ILogger(<T>) implementations around.

Nsubstitute executing Action as parameter on a mocked interface

Is there anyway I can execute an action as a parameter from a mocked out service?
I have an interface that is used in the method I am unit testing:
interface IMyTracker
{
void TrackerMethod(string name, Action action);
}
This is the method I want to unit test:
private void Method1(IMyTracker myTracker)
{
myTracker.TrackerMethod("Method1",() =>
{
// This is stuff I want to execute!
}
}
Here is my unit test
[Test]
public void TestMethod1()
{
var trackerSub = Substitute.For<IMyTracker>();
trackerSub.TrackerMethod(Arg.Any<string>(), Arg.Invoke<Action>()); //How do I execute the logic inside the lambda expression action? Is it at all possible? Or once it's mocked, is that logic lost?
GetClassInstance().Method1(trackerSub);
}
Any help here would be great.
i created example code which show you how it works.
So at the start we get you interface:
public interface ITracker
{
void TrackerMethod(string name, Action action);
}
Next we got the sample class which use this interface and do any action in the tracker, look here:
public class AnyClass
{
private readonly ILogger _anyLogger;
public AnyClass(ILogger anyLogger)
{
this._anyLogger = anyLogger;
}
public void AnyMethod(ITracker tracker)
{
tracker.TrackerMethod("mymethod", () =>
{
_anyLogger.LogError("i was here");
});
}
}
and the unit test for this scenario can look like:
[Fact]
public void TestMethod1()
{
var logger = Substitute.For<ILogger>();
var tracker = Substitute.For<ITracker>();
tracker.TrackerMethod(Arg.Any<string>(), Arg.Invoke());
AnyClass anyClass = new AnyClass(logger);
anyClass.AnyMethod(tracker);
logger.Received().LogError("i was here");
}

How to resolve instances with Castle Windsor that rely on values from the HttpRequestMessage

I'm using Web Api with the OWIN pipeline.
Startup.cs
public class Startup {
public void Configuration(IAppBuilder app) {
var container = new WindsorContainer().Install(FromAssembly.This());
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
// extension method to resolve controllers with Windsor.
app.UseWindsorApi(config, container);
}
}
MyClassInstaller.cs (IWindsorInstaller)
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<IMyClass>().ImplementedBy<MyClass>()
.LifeStyle.PerWebRequest()
.DependsOn(new {
configSetting = ConfigurationManager.AppSettings["key"],
otherSetting = ???
}));
}
MyClass.cs & IMyClass.cs
public class MyClass : IMyClass {
private readonly string configSetting;
private readonly string otherSetting;
public MyClass(string configSetting, string otherSetting) {
this.configSetting = configSetting;
this.otherSetting = otherSetting;
}
public void DoSomething() {
// method that uses the settings that were set in the constructor.
}
}
public interface IMyClass {
void DoSomething();
}
MyController.cs
public class MyController : ApiController {
private readonly IMyClass myClass;
public MyController(IMyClass myClass) {
this.myClass = myClass;
}
[HttpGet]
[Route("")]
public async Task<IHttpActionResult> GetAsync() {
// uses this.myClass
}
}
Here's where I'm stuck. Whenever an instance of MyClass is resolved the value of otherSetting needs to be assigned.
The value of otherSetting is determined by two things.
1) The client_id claims value from the request.
2) An async call to a method that takes the client_id as a parameter and returns a string value. Which is what gets set into otherSetting
public async Task<string> GetOtherSetting(string client_id) {
return "value";
}
I'm not sure where to even begin to get Castle to inject a value based on those two criteria...
UPDATE:
I've updated to potatopeelings answer with some minor changes and it seems to be working fine.
.DynamicParameters(async (k, p) =>
{
var fundNameProvider = k.Resolve<IFundNameValueProvider>();
p["otherSetting"] = await fundNameProvider.GetFundNameAsync();
k.ReleaseComponent(fundNameProvider);
}))
I changed it to an async lambda so I can await the method.
I also called ReleaseComponent as I was under the impression that objects you manually Resolved with Castle you also needed to manually release.
Use UsingFactoryMethod and DynamicParamters
First, inject the current claims
...
Component.For<ClaimsIdentity>().UsingFactoryMethod(() => HttpContext.Current.User.Identity as ClaimsIdentity).LifestylePerWebRequest()
...
into a service (IOtherValueProvider - PerWebRequest) that has a GetOtherSetting method to wait on an async call (i.e. convert the async call to a synchronous call) to get otherSetting from the client_id extracted from the injected ClaimsIdentity
Then use DynamicParameters to get the value
... register your class ...
.DynamicParameters((kernel, parameters) =>
{
parameters["otherSetting"] = kernel.Resolve<IOtherValueProvider>().GetOtherSetting();
}))

Categories