I can't argue with Jordi's answer, it's the same basic answer that I'd provide for an XrmUnitTest based unit test. I'll also give two conventions that I've developed to make this type of change more "automagic". These will be XrmUnitTest examples, but you (or @Jordi) could implement them in the FakeXrmEasy framework.
Option #1 Entity Fluent Builder
Create a fluent OrderNumber Builder. By default, have it default the Order Number to a particular number, or accept a value even:
public class SalesOrderBuilder : EntityBuilder<SalesOrder>
{
public SalesOrder SalesOrder { get; set; }
public SalesOrderBuilder()
{
SalesOrder = new SalesOrder();
WithOrderNumber();
}
public SalesOrderBuilder(Id id)
: this() { Id = id; }
#region Fluent Methods
public SalesOrderBuilder WithOrderNumber(string orderNumber = null)
{
orderNumber = orderNumber ?? "2";
SalesOrder.OrderNumber = orderNumber;
return this;
}
#endregion // Fluent Methods
protected override SalesOrder BuildInternal() { return SalesOrder; }
}
Then you would call this when you're initializing your test data:
private class Example : TestMethodClassBase
{
// Ids struct is used by the TestMethodClassBase to clean up any entities defined
private struct Ids
{
public static readonly Id<SalesOrder> SalesOrder = new Id<SalesOrder>("7CF2BB0D-85D4-4B8C-A7B6-371D3C6EA37C");
}
protected override void InitializeTestData(IOrganizationService service)
{
new SalesOrderBuilder(Ids.SalesOrder).Create(service);
}
protected override void Test(IOrganizationService service)
{
// Run test
Assert.IsNotNull(service.GetFirst<SalesOrder>().OrderNumber);
}
}
Option #2 Fluent Organization Service Builder
Create a Fluent OrganizationServiceBuilder. Have it default to Adding Order Numbers:
public class OrganizationServiceBuilder : DLaB.Xrm.Test.Builders.OrganizationServiceBuilderBase<OrganizationServiceBuilder>
{
protected override OrganizationServiceBuilder This
{
get { return this; }
}
#region Constructors
public OrganizationServiceBuilder() : this(TestBase.GetOrganizationService()) {}
public OrganizationServiceBuilder(IOrganizationService service) : base(service) { WithSalesOrderNumbersDefaulted(); }
#endregion Constructors
#region Fluent Methods
private static int _salesNumber = 1;
public OrganizationServiceBuilder WithSalesOrderNumbersDefaulted() {
WithFakeCreate((s, e) =>
{
if (e.LogicalName == SalesOrder.EntityLogicalName && e.GetAttributeValue<string>(SalesOrder.Fields.OrderNumber) == null)
{
_salesNumber++; //Use Interlocking if thread safe is required
e[SalesOrder.Fields.OrderNumber] = _salesNumber;
}
return s.Create(e);
});
return this;
}
#endregion Fluent Methods
}
Then your test would just wrap that when you create it:
private class Example : TestMethodClassBase
{
// Ids struct is used by the TestMethodClassBase to clean up any entities defined
private struct Ids
{
public static readonly Id<SalesOrder> SalesOrder = new Id<SalesOrder>("7CF2BB0D-85D4-4B8C-A7B6-371D3C6EA37C");
}
protected override void InitializeTestData(IOrganizationService service)
{
service = new OrganizationServiceBuilder(service).WithSalesOrderNumbersDefaulted().Build();
service.Create(new SalesOrder());
}
protected override void Test(IOrganizationService service)
{
// Run test
Assert.IsNotNull(service.GetFirst<SalesOrder>().OrderNumber);
}
}
Using either of these options will allow you to easily specify you want the auto-order-number defaulted, without you having to default it in every test. And if you add it to you test base class, you would have it set automatically.
Update 1
In response to OP's Update, unit testing a method that creates the entity.
Use the Fluen tOrganization Builder like so:
private class Example : TestMethodClassBase
{
protected override void Test(IOrganizationService service)
{
service = new OrganizationServiceBuilder(service)
.WithSalesOrderNumbersDefaulted()
.Build();
// Execute Function for test
var id = Example.ValidateAndCreateOrderAndDetail(service);
Assert.IsNotNull(service.GetEntity<SalesOrder>(id).OrderNumber);
}
}
When your ValidateAndCreateOrderDetail method runs, any SalesOrder that gets created will have a SalesOrder Number populated.