Skip to content

Commit

Permalink
Merge branch 'master' into feature/app-faker
Browse files Browse the repository at this point in the history
# Conflicts:
#	README.md
#	src/FakerDotNet/Faker.cs
#	src/FakerDotNet/FakerContainer.cs
#	tests/FakerDotNet.Tests/FakerContainerTests.cs
#	tests/FakerDotNet.Tests/FakerTests.cs
  • Loading branch information
mrstebo committed Sep 20, 2018
2 parents fe21447 + cbeece5 commit 32edd7e
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Contents
- [Installing](#installing)
- [Usage](#usage)
- [Faker.App](doc/app.md)
- [Faker.Fake](doc/fake.md)
- [Faker.Name](doc/name.md)
- [Faker.Random](doc/random.md)

Expand Down
7 changes: 7 additions & 0 deletions doc/fake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Faker.Fake

```cs
Faker.Fake.F("{Name.FirstName}") //=> "John"
Faker.Fake.F("{Name.FirstName} {Name.LastName}") //=> "John Smith"
```
1 change: 1 addition & 0 deletions src/FakerDotNet/Faker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public static class Faker
private static readonly IFakerContainer Container = new FakerContainer();

public static IAppFaker App { get; } = Container.App;
public static IFakeFaker Fake { get; } = Container.Fake;
public static INameFaker Name { get; } = Container.Name;
public static IRandomFaker Random { get; } = Container.Random;
}
Expand Down
5 changes: 4 additions & 1 deletion src/FakerDotNet/FakerContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@ namespace FakerDotNet
internal interface IFakerContainer
{
IAppFaker App { get; }
IFakeFaker Fake { get; }
INameFaker Name { get; }
IRandomFaker Random { get; }
}

internal class FakerContainer : IFakerContainer
{
public IAppFaker App { get; }
public IFakeFaker Fake { get; }
public INameFaker Name { get; }
public IRandomFaker Random { get; }

public FakerContainer()
{
App = new AppFaker(this);
Fake = new FakeFaker(this);
Name = new NameFaker(this);
Random = new RandomFaker();
}
Expand Down
63 changes: 63 additions & 0 deletions src/FakerDotNet/Fakers/FakeFaker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using System.Reflection;
using System.Text.RegularExpressions;

namespace FakerDotNet.Fakers
{
public interface IFakeFaker
{
string F(string format);
}

internal class FakeFaker : IFakeFaker
{
private readonly IFakerContainer _fakerContainer;

public FakeFaker(IFakerContainer fakerContainer)
{
_fakerContainer = fakerContainer;
}

public string F(string format)
{
if (string.IsNullOrEmpty(format)) throw new FormatException("A string must be specified");

var result = format;
Match match;
while ((match = Regex.Match(result, @"\{(\w+).(\w+)\}")).Success)
{
var matchData = ExtractMatchDataFrom(match);
var faker = GetFaker(matchData.faker);
var value = GetValue(faker, matchData.method);

result = $"{result.Substring(0, match.Index)}{value}{result.Substring(match.Index + match.Length)}";
}

return result;
}

private PropertyInfo GetFaker(string name)
{
var propertyInfo = _fakerContainer.GetType().GetProperty(name);

return propertyInfo ?? throw new FormatException($"Invalid module: {name}");
}

private string GetValue(PropertyInfo propertyInfo, string methodName)
{
var method = propertyInfo.PropertyType.GetMethod(methodName);

if (method == null) throw new FormatException($"Invalid method: {propertyInfo.Name}.{methodName}");

return Convert.ToString(method.Invoke(propertyInfo.GetValue(_fakerContainer, null), new object[] { }));
}

private static (string faker, string method) ExtractMatchDataFrom(Match match)
{
var className = match.Groups[1].Value;
var methodName = match.Groups[2].Value;

return (className, methodName);
}
}
}
6 changes: 6 additions & 0 deletions tests/FakerDotNet.Tests/FakerContainerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ public void App_returns_IAppFaker()
Assert.IsInstanceOf<IAppFaker>(_fakerContainer.App);
}

[Test]
public void Fake_returns_IFakeFaker()
{
Assert.IsInstanceOf<IFakeFaker>(_fakerContainer.Fake);
}

[Test]
public void Name_returns_INameFaker()
{
Expand Down
6 changes: 6 additions & 0 deletions tests/FakerDotNet.Tests/FakerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ public void App_returns_IAppFaker()
Assert.IsInstanceOf<IAppFaker>(Faker.App);
}

[Test]
public void Fake_returns_IFakeFaker()
{
Assert.IsInstanceOf<IFakeFaker>(Faker.Fake);
}

[Test]
public void Name_returns_INameFaker()
{
Expand Down
81 changes: 81 additions & 0 deletions tests/FakerDotNet.Tests/Fakers/FakeFakerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System;
using FakeItEasy;
using FakerDotNet.Fakers;
using NUnit.Framework;

namespace FakerDotNet.Tests.Fakers
{
[TestFixture]
[Parallelizable]
public class FakeFakerTests
{
[SetUp]
public void SetUp()
{
_fakerContainer = A.Fake<IFakerContainer>();
_fakeFaker = new FakeFaker(_fakerContainer);
}

private IFakerContainer _fakerContainer;
private IFakeFaker _fakeFaker;

[Test]
public void F_returns_filled_in_string()
{
const string format = "{Name.FirstName} {Name.LastName}";

A.CallTo(() => _fakerContainer.Name.FirstName()).Returns("John");
A.CallTo(() => _fakerContainer.Name.LastName()).Returns("Smith");

Assert.AreEqual("John Smith", _fakeFaker.F(format));
}

[Test]
public void F_handles_duplicate_placeholders()
{
const string format = "{Name.FirstName} {Name.FirstName}";

A.CallTo(() => _fakerContainer.Name.FirstName()).ReturnsNextFromSequence("Test1", "Test2");

Assert.AreEqual("Test1 Test2", _fakeFaker.F(format));
}

[Test]
public void F_with_null_throws_FormatException()
{
var ex = Assert.Throws<FormatException>(() => _fakeFaker.F(null));

Assert.AreEqual("A string must be specified", ex.Message);
}

[Test]
public void F_with_empty_string_throws_FormatException()
{
const string format = "";

var ex = Assert.Throws<FormatException>(() => _fakeFaker.F(format));

Assert.AreEqual("A string must be specified", ex.Message);
}

[Test]
public void F_with_invalid_faker_throws_FormatException()
{
const string format = "{Unknown.Test}";

var ex = Assert.Throws<FormatException>(() => _fakeFaker.F(format));

Assert.AreEqual("Invalid module: Unknown", ex.Message);
}

[Test]
public void F_with_invalid_method_throws_FormatException()
{
const string format = "{Name.BadMethod}";

var ex = Assert.Throws<FormatException>(() => _fakeFaker.F(format));

Assert.AreEqual("Invalid method: Name.BadMethod", ex.Message);
}
}
}

0 comments on commit 32edd7e

Please sign in to comment.