Create a list with specific values with Autofixture C# - c#

The Model has properties Id, Code etc.
I want to create 4 data with specific different codes.
var data = _fixture.Build<MyModel>()
.With(f => f.Code, "A")
.CreateMany(4);
This results in all 4 data with Code "A". I want the 4 data to have codes "A", "B", "C", "D"
Thanks in Advance

There is an easier way to do this
string[] alphabets = { "A", "B", "C", "D" };
var queue = new Queue<string>(alphabets);
var data = _fixture.Build<MyModel>()
.With(f => f.Code, () => queue.Dequeue())
.CreateMany(alphabets.Length);
Output
[
{Code: "A"},
{Code: "B"},
{Code: "C"},
{Code: "D"}
]
In case if you want the result in reverse order use Stack instead of Queue and Pop instead of Dequeue

Assuming you only need 4 items you can define your collection of codes and use it to generate the 4 models using LINQ.
public static object[][] Codes =
{
new object[] { new[] { "A", "B", "C", "D" } }
};
[Theory]
[MemberAutoData(nameof(Codes))]
public void Foo(string[] codes, Fixture fixture)
{
var builder = fixture.Build<MyModel>(); // Do any other customizations here
var models = codes.Select(x => builder.With(x => x.Code, x).Create());
var acutal = models.Select(x => x.Code).ToArray();
Assert.Equal(codes, acutal);
}
public class MyModel
{
public int Id { get; set; }
public string Code { get; set; }
}

This seems ripe for an extension method:
public static IPostprocessComposer<T> WithValues<T, TProperty>(this IPostprocessComposer<T> composer,
Expression<Func<T, TProperty>> propertyPicker,
params TProperty[] values)
{
var queue = new Queue<TProperty>(values);
return composer.With(propertyPicker, () => queue.Dequeue());
}
// Usage:
var data = _fixture.Build<MyModel>()
.WithValues(f => f.Code, "A", "B", "C", "D")
.CreateMany(4);

Related

Create a list with items from first group

I am using a list collection with two properties Name and Group.
I need to create a list collection which it will contain only elements from first group, then another list with elements from the second group and finally the third group.
My code:
public class Person
{
public string Name { get; set; }
public string Group { get; set; }
}
private void button1_Click(object sender, EventArgs e)
{
var mItems = new List<Person>();
mItems.Add(new Person{ Name="A", Group="1", });
mItems.Add(new Person { Name = "B", Group = "1", });
mItems.Add(new Person { Name = "C", Group = "2", });
mItems.Add(new Person { Name = "D", Group = "2", });
mItems.Add(new Person { Name = "E", Group = "3", });
mItems.Add(new Person { Name = "F", Group = "3", });
mItems.Add(new Person { Name = "G", Group = "1", });
}
I need to create a list with elements which are on the first group, example group "1".( i notice that this is an example, i don't not know the exactly group name in my application, it can be anything)
So my expected result is a list with A,B and G, then a second list with C,D and finally a third list with E,F. I have found code below:
var results = mItems.GroupBy(x => x.Group)
.Select(g => g.OrderBy(x => x.Group).FirstOrDefault());
But i am taking the exactly oposite result. I am taking only the first element of each group.
You need to place your FirstOrDefault() call after your Select() as it's currently inside of the select, which is causing the first of each group to be selected:
var results = mItems.GroupBy(x => x.Group)
.Select(g => g.OrderBy(x => x.Group))
.FirstOrDefault();
Likewise, if you wanted to output every group, you could just remove the FirstOrDefault() call altogether. This would return a collection of ordered collections, which you could access individually via the ElementAt() function:
var results = mItems.GroupBy(x => x.Group)
.Select(g => g.OrderBy(x => x.Group))
.ElementAt(someIndex);
Example
You can see a working example here.

IEnumerable interface TDD using Mock in C# [duplicate]

This question already has answers here:
Testing a function that returns IEnumerable<string>
(2 answers)
Closed 4 years ago.
Below is the FizzBuzz Generation Code,
public class BusinessHandler : IBusinessHandler
{
private readonly IEnumerable<IBusinessRule> BusinessRule;
public BusinessHandler(IEnumerable<IBusinessRule> businessrule)
{
this.BusinessRule = businessrule;
}
public IEnumerable<string> GetResult(int inputValue)
{
var outputList = new List<string>();
for (int element = 1; element <= inputValue; element++)
{
string tempOutput = element.ToString();
var divisionResult = this.BusinessRule.FirstOrDefault(x => x.IsDivisible(element));
if (divisionResult != null)
{
tempOutput = divisionResult.PrintOutput();
}
outputList.Add(tempOutput);
}
return outputList;
}
}
Here IBusinessHandler, IBusinessRule are the interface. Using Dependency Injection, i am calling this method in my web application.
IBusinessRule :
public interface IBusinessRule
{
bool IsDivisible(int inputValue);
string PrintOutput();
}
3 classes are implementing IBusinessRule interface.
I am new to TDD, how can I implement unit test for GetResult() method.
For TDD i am using Nunit,Moq packages.
A test for the provided code can look like this
[TestClass]
public class BusinessHandlerTests {
[TestMethod]
public void BusinessHandler_Should_GetResult() {
//Arrange
var fizz = new Mock<IBusinessRule>();
fizz.Setup(_ => _.IsDivisible(It.IsAny<int>()))
.Returns((int value) => value % 3 == 0);
fizz.Setup(_ => _.PrintOutput()).Returns("Fizz");
var buzz = new Mock<IBusinessRule>();
buzz.Setup(_ => _.IsDivisible(It.IsAny<int>()))
.Returns((int value) => value % 5 == 0);
buzz.Setup(_ => _.PrintOutput()).Returns("Buzz");
var fizzbuzz = new Mock<IBusinessRule>();
fizzbuzz.Setup(_ => _.IsDivisible(It.IsAny<int>()))
.Returns((int value) => value % 15 == 0);
fizzbuzz.Setup(_ => _.PrintOutput()).Returns("FizzBuzz");
var businessRule = new[] {
fizzbuzz.Object, fizz.Object, buzz.Object // <--order is important
};
var subject = new BusinessHandler(businessRule);
var inputValue = 15;
var expected = new[] { "1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz", "11", "Fizz", "13", "14", "FizzBuzz" };
//Act
var actual = subject.GetResult(inputValue);
//Assert
actual.Should().BeEquivalentTo(expected);
}
}
Assuming the business rules have not already been defined, they can be mocked and injected into the subject under test, as demonstrated above.
If for example the classes already existed
public class FizzObject : IBusinessRule {
public bool IsDivisible(int inputValue) => inputValue % 3 == 0;
public string PrintOutput() => "Fizz";
}
then they can be initialized
var businessRule = new[] { new FizzBuzzObject(), new FizzObject(), new BuzzObject() }; // <--order is important
and injected into the subject under test with the same expected behavior
You don't need mocks for testing "FizzBuzz".
As you said you have 3 implementations of IBusinessRule
public class RuleOne : IBusinessRule { ... }
public class RuleTwo : IBusinessRule { ... }
public class RuleThree : IBusinessRule { ... }
Then you can write test which cover whole logic. With this kind of test you will test BusinessHandler and all implementations of IBusinessRule will be tested as well.
With this test you will have freedom to redesign how BusinessHandler implemented (possibly need to change only constructor)
// Here used NUnit feature of TestCase to provide values to the test function
[Test]
[TestCase(1, new[] { "1" })]
[TestCase(3, new[] { "Fizz" })]
[TestCase(5, new[] { "Buzz" })]
[TestCase(15, new[] { "Fizz", "Buzz" })]
[TestCase(20, new[] { "20" })]
public void ShouldReturnExpectedResult(int input, string[] expected)
{
// Arrange
var rules = new[]
{
new RuleOne();
new RuleTwo();
new RuleThree();
}
var handler = new BusinessHandler(rules);
// Act
var actual = handler.GetResult(input);
// Assert
actual.Should().BeEquivalent(expected);
}

LINQ select into array

I am trying to modify a LINQ query to select some properties into an array but am struggling to achieve part of it.
toRun.AddRange(entity.Properties
.Select(property => property.PrimaryField)
.Select(field => new { field, entity = entity.EntityName, table = field.Table, key = entity.EntityIdField })
I need this amending so that if a second property called SecondaryField is not null or empty string it will be added to the results of the first Select statement.
For example if entity.Properties contains:
Property { PrimaryField = "a", SecondaryField = "b" },
Property { PrimaryField = "c", SecondaryField = "" }
I would like the first Select statement to return:
{ "a", "b", "c" }
Appreciate any help thanks.
This seems to reproduce what you want: you have a class with two properties:
public class Foo
{
public string Bar { get; set; }
public string Baz { get; set; }
}
Of which you have a collection:
var foos = new List<Foo>
{
new Foo { Bar = "a", Baz = "b" },
new Foo { Bar = "c", Baz = "" },
};
And from this collection, you want to select all properties that have a non-empty value into an array.
You can do so using SelectMany():
var result = foos.SelectMany(f => new[] { f.Bar, f.Baz })
.Where(p => !string.IsNullOrWhiteSpace(p))
.ToArray();
You select a new array containing the value of both properties, then filter out the values you don't want, and turn the result into an array again.
This should be pretty simple - get both fields, use a Where to remove the null/empties and turn to an array:
var result = entity.Properties.SelectMany(p =>new[]{ p.PrimaryField,p.SecondaryField})
.Where(x => !String.IsNullOrEmpty(x))
.ToArray();
Live example: http://rextester.com/MHM61977

Mock a Custom Collection using Moq

I have the following types in a 3rd party library
public interface IWorkbook : IPrintable
{
...
IWorksheets Worksheets { get; }
}
The worksheets interface is
public interface IWorksheets : IEnumerable
{
IWorksheet this[int index] { get; }
IWorksheet this[string name] { get; }
IWorkbookSet WorkbookSet { get; }
IWorksheet Add();
IWorksheet AddAfter(ISheet sheet);
IWorksheet AddBefore(ISheet sheet);
bool Contains(IWorksheet worksheet);
}
I have a method that I want to unit test that takes an IWorkbook and iterates through the contained worksheets. My problem is how I can use Moq to create a mock collection for IWorksheets. The IWorksheet interface is
public IWorksheet
{
...
public Name { get; set; } // This is the only property I am interested in.
}
So how can I generate a fake IWorkbook which has a fake collection (IWorksheets) of IWorksheets?
I have started out with
[TestInitialize]
public void Initialize()
{
List<string> fakeSheetNames = new List<string>()
{
"Master",
"A",
"B",
"C",
"__ParentA",
"D",
"wsgParentB",
"E",
"F",
"__ParentC",
"__ParentD",
"G"
};
List<IMock<IWorksheet>> sheetMockList = new List<IMock<IWorksheet>>();
foreach (string name in fakeSheetNames)
{
Mock<IWorksheet> tmpMock = new Mock<IWorksheet>();
tmpMock.Setup(p => p.Name).Returns(name);
sheetMockList.Add(tmpMock);
}
var mockWorksheets = new Mock<IWorksheets>();
mockWorksheets.Setup(p => p).Returns(sheetMockList);
...
}
But I cannot do this as (obviously)
cannot convert from 'System.Collections.Generic.List>' to 'SpreadsheetGear.IWorksheets'
How can I mock the IWorksheets collection?
So I now have the following code to create my mocks as per the answer below
[TestClass]
public class WorkbookStrucutreProviderTests
{
private Mock<IWorkbookSet> mockWorkbookSet;
private readonly List<string> parentPrefixes = new List<string>() { "__", "wsg" };
[TestInitialize]
public void Initialize()
{
List<string> fakeSheetNames = new List<string>()
{
"Master",
"A",
"B",
"C",
"__ParentA",
"D",
"wsgParentB",
"E",
"F",
"__ParentC",
"__ParentD",
"G"
};
List<IWorksheet> worksheetMockList = new List<IWorksheet>();
foreach (string name in fakeSheetNames)
{
Mock<IWorksheet> tmpMock = new Mock<IWorksheet>();
tmpMock.Setup(p => p.Name).Returns(name);
tmpMock.Setup(p => p.Visible)
.Returns(parentPrefixes.Any(p => name.StartsWith(p)) ?
SheetVisibility.Hidden :
SheetVisibility.Visible);
worksheetMockList.Add(tmpMock.Object);
}
List<IWorkbook> workbookMockList = new List<IWorkbook>();
Mock<IWorkbook> mockWorkbook = new Mock<IWorkbook>();
mockWorkbook
.Setup(p => p.Worksheets.GetEnumerator())
.Returns(worksheetMockList.GetEnumerator());
workbookMockList.Add(mockWorkbook.Object);
mockWorkbookSet = new Mock<IWorkbookSet>();
mockWorkbookSet
.Setup(p => p.Workbooks.GetEnumerator())
.Returns(workbookMockList.GetEnumerator());
}
[TestMethod]
public async Task StrucutreGenerationAsyncTest()
{
WorkbookStructureProvider provider = new WorkbookStructureProvider();
await provider.GenerateWorkbookStructureAsync(mockWorkbookSet.Object);
foreach (var item in provider.Structure)
{
Trace.WriteLine("--" + item.Name);
if (item.HasChildren)
{
foreach (var child in item.Children)
{
Trace.WriteLine("-- --" + child.Name);
}
}
}
}
But in the GenerateWorkbookStructureAsync() method I have this bit of code
bool IsUserCostWorkbook = false;
if (workbook.Worksheets.Cast<IWorksheet>().Any(
ws => ws.Name.CompareNoCase(Keywords.Master)))
{
// TODO Extra check for UserCost template.
IsUserCostWorkbook = true;
}
and here the workbook.Worksheets collection is empty. I thought my mock GetEnumerator would handle this; it doesn't.
So how can I mock the IWorksheets so that I can do the following?
foreach (var ws in workbook.Worksheets.Cast<IWorksheet>())
{
...
}
The following example passes when tested
[TestMethod]
public void Mock_Custom_Collection_Using_Moq() {
//Arrange
var parentPrefixes = new List<string>() { "__", "wsg" };
var fakeSheetNames = new List<string>(){
"Master",
"A",
"B",
"C",
"__ParentA",
"D",
"wsgParentB",
"E",
"F",
"__ParentC",
"__ParentD",
"G"
};
var worksheetMockList = new List<IWorksheet>();
foreach (string name in fakeSheetNames) {
var worksheet = Mock.Of<IWorksheet>();
worksheet.Name = name;
worksheet.Visible = parentPrefixes.Any(p => name.StartsWith(p)) ?
SheetVisibility.Hidden :
SheetVisibility.Visible;
worksheetMockList.Add(worksheet);
}
var mockWorkbook = new Mock<IWorkbook>();
mockWorkbook
.Setup(p => p.Worksheets.GetEnumerator())
.Returns(() => worksheetMockList.GetEnumerator());
var workbook = mockWorkbook.Object;
//Act
bool IsUserCostWorkbook = false;
if (workbook.Worksheets.Cast<IWorksheet>()
.Any(ws => ws.Name.Equals("Master", StringComparison.InvariantCultureIgnoreCase))) {
IsUserCostWorkbook = true;
}
//Assert
Assert.IsTrue(IsUserCostWorkbook);
}
Sorry for pseudo code:
var fakeWorksheet = new Mock<IWorksheet>();
//You can use AutoFixture here to auto-populate properties or you can set only required props
fakeWorksheet.Setup(p => p.Name).Returns("TestName");
var worksheetsMock = new Mock<IWorksheets>()
//here mock some members that you need
worksheetsMock.Setup(w => w.Add()).Returns(fakeWorksheet.Object);
var workbookMock = new Mock<IWorkbook>();
workbookMock.Setup(w => w.Worksheets).Returns(worksheetsMock.Object);

Linq custom query with object properties

I want know to make a query using linq, between a collection of objects
and a collection of values. In the sample code below, I make the question about it.
class USER
{
public string Name { get; set; }
}
public class MyClass
{
public MyClass()
{
List<USER> listUser = new List<USER>();
listUser.Add(new USER { Name = "A" });
listUser.Add(new USER { Name = "B" });
listUser.Add(new USER { Name = "C" });
listUser.Add(new USER { Name = "D" });
string[] arrayNames = { "A", "B" };
}
}
Using Linq how can I get all USER in listUser with them Name equals to the arrayNames values.?
The expected results wold be
//listUser[0] --> User with Name == "A"
//listUser[1] --> User with Name == "B"
Thanks in advance.
HashSet<string> names = new HashSet<string>(new string[]{ "A", "B" });
var selectedUsers = listUser.Where(user => names.Contains(user.Name));
The hashset is optional and overkill if you have only a few users but it guarantees optimal lookup performance if you have a lot of users.
listUser.Where(u => arrayNames.Contains(u.Name)).ToList();
This should so what you want, tried it in a console app. Worked a treat
var query = listUser.Where(i => arrayNames.Contains(i.Name));
foreach (var item in query)
{
Console.WriteLine(item.Name);
}
Console.ReadKey();
The key part is the arrayNames.Contains(i.Name) as this is inverse to intuition in that you specify the IEnumerable and then the linq parameter inside the contains method.
listUser = (from u in listUser where arrayNames.Contains(u.Name) select u).ToList();

Categories

Resources