Here is the class I am trying to mock. Helper class that has a static method. Which takes in a dataTable.
public class DataTableHelpers
{
public static ArrayList GetDataTableColumns(DataTable dataTable)
{
if (dataTable == null)
{
throw new ArgumentNullException(nameof(dataTable));
}
var columnsCount = dataTable.Columns.Count;
var columnHeadings = new ArrayList();
for (var i = 0; i < columnsCount; i++)
{
var dataColumn = dataTable.Columns[i];
columnHeadings.Add(dataColumn.ColumnName.ToString());
}
return columnHeadings;
}
}
Tried using ShimsContext. Here is the snippet I have come up with. Want to mock when datatable is null and not null.
public void GivenDatatableIsNUllShouldThrowNullException()
{
var expected = new ArrayList();
//ARRANGE
using (ShimsContext.Create())
{
dataTableHelpers = new DataTableHelpers();
//ACT
var result = ShimDataTableHelpers.GetDataTableColumnsDataTable = (s) =>
{
Should.Throw<ArgumentNullException>(() =>
{
});
throw new ArgumentNullException(nameof(s));
};
//Assert
Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AreNotEqual(result, expected);
}
}
Your question is a little unclear but I think what you're after is a way to test code that is using the given static helper method. It's easy to test the static helper, it's not so easy to test code that's using those helpers. When you run into something like I've found it best to refactor that code to not use static helpers. Instead push that code into a class that you can abstract and inject into places you need it. But sometimes that's easier said than done.
As a stop gap you can incrementally move to that direction by introducing a class to hold the actual code that you can then swap out when testing. This doesn't use MS Fakes but it's a technique that you can use to help make your code more testable.
I'm sorry I can't recall who first came up with this method, it certainly wasn't me. But here's the idea:
Create a class to hold the logic:
public class DataTableHelperImpl : IDataTableHelperImpl
{
public ArrayList GetDataTableColumns(DataTable dataTable)
{
if (dataTable == null)
{
throw new ArgumentNullException(nameof(dataTable));
}
var columnsCount = dataTable.Columns.Count;
var columnHeadings = new ArrayList();
for (var i = 0; i < columnsCount; i++)
{
var dataColumn = dataTable.Columns[i];
columnHeadings.Add(dataColumn.ColumnName.ToString());
}
return columnHeadings;
}
}
With the associated interface that you can then mock:
public interface IDataTableHelperImpl
{
public ArrayList GetDataTableColumns(DataTable dataTable);
}
Then use this in your static helper:
public static class Helper
{
public static IDataTableHelperImpl implementation = new DataTableHelperImpl();
public static ArrayList GetDataTableColumns(DataTable dataTable)
{
return implementation.GetDataTableColumns(dataTable);
}
}
Now in your test you can swap out that class to mock whatever behavior you want.
[Fact]
public void Test1()
{
var implMock = Mock.Of<IDataTableHelperImpl>();
Helper.implementation = implMock;
// whatever you need to test...
}
Related
I am trying to write an Update Test for different products (which are classes in this case) and different time steps :
public class UpdateTest
{
private static Product ProductLastYear;
private static Product ProductTwoYearsAgo;
public UpdateTest(Product product)
{
var previousReleasedProducts = new Products();
ProductLastYear = previousReleasedProducts.GetProduct(Years.GetLastYear());
ProductTwoYearsAgo = previousReleasedProducts.GetProduct(Years.GetTwoYearsAgo());
}
Each product needs to be installed, and afterwards it is checked if the installation was successful (this is basically a pre-step before the Update). Right now, I am using two Tests for this:
[Test, Category("UpdateLastYear")), Order((int) NunitTestOrderEnum.Order.First)]
public void InstallPreviousReleasedProduct()
{
using (var controller = new BootstrapperController(ProductLastYear))
{
controller.Install();
}
var successfulInstallation = InstallationValidator.ValidateInstall(ProductLastYear);
Assert.That(successfulInstallation, Is.True);
}
[Test, Category("UpdateTwoYearsAgo"), Order((int) NunitTestOrderEnum.Order.First)]
public void InstallTwoYearsAgoProduct()
{
using (var controller = new BootstrapperController(ProductTwoYearsAgo))
{
controller.Install();
}
var successfulInstallation = InstallationValidator.ValidateInstall(ProductTwoYearsAgo);
Assert.That(successfulInstallation, Is.True);
}
Now, both tests have some code redundancy, which I would like to avoid. I was thinking about using TestCases for this, something like :
[TestCase(ProductLastYear), Category("UpdateLastYear"), Order((int) NunitTestOrderEnum.Order.First)]
[TestCase(ProductTwoYearsAgo), Category("UpdateTwoYearsAgo"), Order((int) NunitTestOrderEnum.Order.First)]
public void InstallPreProduct(Product product)
{
using (var controller = new BootstrapperController(product))
{
controller.Install();
}
var successfulInstallation = InstallationValidator.ValidateInstall(product);
Assert.That(successfulInstallation, Is.True);
}
Is something like this possible? I tried different Syntax for that approach, but it does not seem to work that easily.
You can only use compile-time constants within attributes. However your static fields are no constants.
You can use the TestCaseSource-attribute:
[TestCaseSource(nameof(ProvideTestcases))]
public void InstallPreProduct(Product product)
{
using (var controller = new BootstrapperController(product))
{
controller.Install();
}
var successfulInstallation = InstallationValidator.ValidateInstall(product);
Assert.That(successfulInstallation, Is.True);
}
public static IEnumerable<TestCaseData> ProvideTestcases()
{
yield return new TestCaseData(ProductLastYear).SetCategory("UpdateLastYear");
yield return new TestCaseData(ProductTwoYearsAgo).SetCategory("UpdateTwoYearsAgo");
}
However that assumes your static fields are already initialized, which isn't the case. So you need a static constructor for your testclass.
[TestFixture]
public UpdateTest
{
public static ProductLastYear;
public static ProductTwoYearsAgo;
static
{
ProductLastYear = ...;
ProductTwoYearsAgo = ...;
}
}
This is pretty much boilerplate for so little duplication. So it's a tradeoff if or of it not this is worth the afford.
Another opportunity is to introduce some static constant, like an enum that reflects the property to be used:
[TestCase(MyEnum.LastYear), Category("UpdateLastYear")]
[TestCase(MyEnum.TwoYearsAgo), Category("UpdateTwoYearsAgo")]
public void InstallPreProduct(MyEnum product)
{
var Product = product == MyEnum.LastYear ?
ProductLastYear :
ProductTwoYearsAgo ;
using (var controller = new BootstrapperController(product))
{
controller.Install();
}
var successfulInstallation = InstallationValidator.ValidateInstall(product);
Assert.That(successfulInstallation, Is.True);
}
An enum is a constant expression, so you can easily use it within the test-attributes.
I created Test for a method that is being tested using MOQ & NUnit. The method to be tested will will another method using an object of that corresponding class. When I try to mock that called method, I am not able to invoke the mocked method. How to mock this method, because my testing method is using the other said method. Please help me on this.
public DataSet ExecuteCondition()
{
var ObjClass1 = new Class1();
....
var result = ObjClass1.VerifyPrecondition(query);
....
}
public class Class1:IClass1
{
public string VerifyPrecondition(string query)
{
....
return text;
}
}
So, I suppose this should look like this:
Class with ExecuteCondition() method:
public class DataClass
{
private readonly IClass1 _class1;
public DataClass(IClass1 class1)
{
_class1 = class1;
}
public DataSet ExecuteCondition()
{
//....
var result = _class1.VerifyPrecondition(query);
//....
}
}
Test:
[Test]
public void Test()
{
var mockClass1 = new Mock<IClass1>();
mockClass1.Setup(x => x.VerifyPrecondition(It.IsAny<string>())).Returns("test");
var dataClass = new DataClass(mockClass1.Object);
dataClass.ExecuteCondition();
//Assert
}
I have an interface:
public interface IRepeater
{
void Each(string path, Action<string> action);
}
I want to mock this interface using Moq. Now I can obviously do the following:
var mock = new Mock<IRepeater>();
mock.Setup(m => m.Each(It.IsAny<string>(), It.IsAny<Action<string>>());
However, to aid testing I want to be able to mock the string that gets passed to the Action<string>. Can this be done with Moq? If yes, how?
Update
To clarify I am testing a different class that has a dependency on IRepeater. I want to mock IRepeater.Each so I can control the string that the Action gets so I can test the behaviour.
Example
So if I have a class like so.
public class Service
{
private readonly IRepeater _repeater;
public Service(IRepeater repeater)
{
_repeater = repeater;
}
public string Parse(string path)
{
var builder = new StringBuilder();
_repeater.Each(path, line => builder.Append(line));
return builder.ToString();
}
}
How do I mock IRepeater.Each so that I can test Service.Parse?
You have to use callback method. Since line => builder.Append(line) is part of the method behavior, you have to execute this behavior when you test the method:
[TestMethod]
public void Test_Service_When_Passing_String_And_ActionDelegate()
{
var fakeReporter = new Mock<IRepeater>();
fakeReporter.Setup(x => x.Each(It.IsAny<string>(), It.IsAny<Action<string>>()))
.Callback<string, Action<string>>((s, action) => action(s));
var target = new Service(fakeReporter.Object);
var result = target.Parse("asdfghj");
Assert.AreEqual("asdfghj", result);
}
Another approach to test this method is to verify the method was called with the correct path and then verify that the action is the correct action:
[TestMethod]
public void Test_Service_When_Passing_String_And_ActionDelegate()
{
var fakeReporter = new Mock<IRepeater>();
fakeReporter.Setup(x => x.Each(It.IsAny<string>(), It.IsAny<Action<string>>()))
.Callback<string, Action<string>>((s, action) =>
{
Assert.AreEqual("asdfghj", s);
foreach (var w in "pass")
{
action(w.ToString());
}
});
var target = new Service(fakeReporter.Object);
var result = target.Parse("asdfghj");
Assert.AreEqual("pass", result);
}
BTW you can replace the It.IsAny<string>() with the string and then remove the Assert.AreEqual("asdfghj", s);(I just like to test things in the explicit way...)
Seems like you are looking to verify that a passed Action (delegate) will be passed to the IRepeater Call. Because you are not testing the Repeater but a Repeater caller (The Repeater is the mock and not the tested subject).
Here is how I would have done it:
public class Service
{
private readonly IRepeater repeater;
public Service(IRepeater repeater)
{
this.repeater = repeater;
}
public void Foo(string str, Action<string> action)
{
repeater.Each(str, action);
}
}
public class ActionImplement
{
public virtual void Action(string str)
{
Console.Write(str);
}
}
public interface IRepeater
{
void Each(string path, Action<string> action);
}
And the test would have verify the passing of ActionImplement.Action
[TestMethod]
public void Test_Service_When_Passing_String_And_ActionDelegate()
{
var actionImplement = new Mock<ActionImplement>();
actionImplement.Setup(m => m.Action(It.IsAny<string>()));
var mock = new Mock<IRepeater>();
mock.Setup(m => m.Each(It.IsAny<string>(), actionImplement.Object.Action));
var srv = new Service(mock.Object);
srv.Foo("aa",actionImplement.Object.Action);
mock.Verify(ai => ai.Each("aa", actionImplement.Object.Action));
}
Anyone have any idea why below still calls YesService?
It almost seems like IYesService is considered separate to YesService..
Any ideas?
public interface IYesService
{
string Hello();
}
public class YesService : IYesService
{
public string Hello()
{
return "Yes";
}
}
class Program
{
static void Main(string[] args)
{
var _mock = new Mock<IYesService>();
_mock.Setup(x => x.Hello()).Returns("No");
var service = new YesService();
var result = service.Hello();
Console.Write(result);
Console.ReadLine();
}
}
Because you don't use the _mock, you instantiate the YesService and call the method on that.
You can use mocking when you consume this interface:
public class ServiceUser
{
private IYesService _yesService;
public ServiceUser(IYesService yesService)
{
_yesService = yesService;
}
public string CallService()
{
return _yesService.Hello();
}
}
Then use it like this:
var serviceMock = new Mock<IYesService>();
serviceMock.Setup(x => x.Hello()).Returns("No");
var service = new ServiceUser(serviceMock.Object);
var result = service.CallService();
You are creating an instance of YesService (the concrete class) in your Main method. The var service line an be done away with, and the var result line should become:
var result = _mock.Object.Hello();
Try that...
I'm trying to create a url builder similar to the one in asp mvc except our methods are frequently changing parameters and breaking pages.
Does anyone know if it's possible to coerce c# into allowing event like syntax to be returned from a delegate like this:
new UrlBuilder2<FakeController>(x => { return x.ActionWithInt; });
The class would be similar to this:
public class UrlBuilder<TController>
{
public UrlBuilder2(Func<TController, TType> action)
{
}
}
Basically I want to know what Type to use for TType. Or if it's at all possible.
Edit -
I would (if possible) like to use just the method, similar to how you would assign an event ( clickEvent =+ myMethod;)
Not exactly sure what you want to achieve, but assuming you want to generate link simlar to this:
MyForm/MyMethod.aspx
based on WebForm (or any other class) like this:
public class MyForm {
public void MyMethod() {
// Something here
}
public void MethodWithParams(int i, string str) {
// Something here
}
}
You can use this builder (test included):
class UrlBuilder2<T> {
private readonly Expression<Func<T, object>> callExpression;
public UrlBuilder2(Expression<Func<T,object>> callExpression) {
this.callExpression = callExpression;
}
public override string ToString() {
MethodCallExpression call = (MethodCallExpression) callExpression.Body;
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}/{1}.aspx", call.Object.Type.Name, call.Method.Name);
var delimiter = "?";
var formalParams = call.Method.GetParameters();
for (int i = 0; i < formalParams.Length; i++) {
var actual = call.Arguments[i];
if (actual == null)
continue; // Do not put NULL to QueryString
var formal = formalParams[i].Name;
sb.AppendFormat("{0}{1}={2}", delimiter, formal, HttpUtility.HtmlEncode(actual.ToString()));
}
return sb.ToString();
}
}
[Test]
public void CanBuildUrlByClassAndMethodName() {
var str = new UrlBuilder2<MyForm>(c => c.MyMethod()).ToString();
str.Should().Be.EqualTo("MyForm/MyMethod.aspx");
}
[Test]
public void CanBuildUrlByMethodWithParams() {
var str = new UrlBuilder2<MyForm>(c => c.MethodWithParams(2, "hello")).ToString();
str.Should().Be.EqualTo("MyForm/MyMethod.aspx?i=2&str=hello");
}
All this will allow you to keep the links type-safe and refactoring advantages will be leveraged.
You will probably need to enhance the UrlBuilder2 but this should get you started.
If you just want to use name of a method to generate links you can do something like this:
class MyClass {
public void MyMethod() {}
}
class UrlBuilder3<T> {
Expression<Func<T, Action>> info;
public UrlBuilder3(Expression<Func<T, Action>> info) {
this.info = info;
}
public override string ToString() {
UnaryExpression exp = (UnaryExpression)info.Body;
MethodCallExpression createDelegate = (MethodCallExpression)exp.Operand;
// 0-Action,1-x,2-Delegate as Constant
ConstantExpression methodArgument = (ConstantExpression)createDelegate.Arguments[2];
MethodInfo method = (MethodInfo)methodArgument.Value;
return string.Format("{0}/{1}.aspx", typeof(T).Name, method.Name);
}
}
[Test]
public void UrlByDelegate() {
new UrlBuilder3<MyClass>(x => x.MyMethod).ToString()
.Should().Be.EqualTo("MyClass/MyMethod.aspx");
}
The tricky thing is correctly resolving the Expression tree. The code above works for this particular sample, but you will need to check it works for all your cases.
You can return a function pointer aka a delegate in c# as below.
public delegate int mydelegate(string s);
public class Test
{
mydelegate MyFunc(string s)
{
return (astring => astring.Length + s.Length);
}
}
This would allow you to attach the output of the function to an event.
var test = new Test();
someevent += test.MyFunc("this is a test");
Assuming that someevent took a function with the same signature as the delegate.