Skip to content

Commit 62ee459

Browse files
authored
Add tests for proxy interface handling (#2066)
See #2052 and #2271
1 parent c60136b commit 62ee459

File tree

5 files changed

+527
-0
lines changed

5 files changed

+527
-0
lines changed
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by AsyncGenerator.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
11+
using System;
12+
using NHibernate.Cfg.MappingSchema;
13+
using NHibernate.Mapping.ByCode;
14+
using NUnit.Framework;
15+
16+
namespace NHibernate.Test.StaticProxyTest.InterfaceHandling
17+
{
18+
using System.Threading.Tasks;
19+
[TestFixture]
20+
public class FixtureAsync : TestCaseMappingByCode
21+
{
22+
private readonly Guid _id = Guid.NewGuid();
23+
24+
protected override HbmMapping GetMappings()
25+
{
26+
var mapper = new ModelMapper();
27+
28+
#region Subclass hierarchy
29+
30+
mapper.Class<EntityClassProxy>(
31+
rc =>
32+
{
33+
rc.Id(x => x.Id);
34+
rc.Property(x => x.Name);
35+
});
36+
37+
mapper.UnionSubclass<SubEntityInterfaceProxy>(
38+
rc =>
39+
{
40+
rc.Proxy(typeof(ISubEntityProxy));
41+
42+
rc.Property(x => x.AnotherName);
43+
});
44+
45+
mapper.UnionSubclass<AnotherSubEntityInterfaceProxy>(
46+
rc =>
47+
{
48+
rc.Proxy(typeof(IAnotherEntityProxy));
49+
50+
rc.Property(x => x.AnotherName);
51+
});
52+
53+
mapper.Class<EntityWithSuperClassInterfaceLookup>(
54+
rc =>
55+
{
56+
rc.Table("ClassWithInterfaceLookup");
57+
rc.Id(x => x.Id);
58+
rc.Property(x => x.Name);
59+
rc.ManyToOne(x => x.EntityLookup, x => x.Class(typeof(EntityClassProxy)));
60+
});
61+
62+
#endregion Subclass hierarchy
63+
64+
mapper.Class<EntitySimple>(
65+
rc =>
66+
{
67+
rc.Id(x => x.Id);
68+
rc.Property(x => x.Name);
69+
});
70+
71+
mapper.Class<EntityExplicitInterface>(
72+
rc =>
73+
{
74+
rc.Id(x => x.Id);
75+
rc.Property(x => x.Name);
76+
});
77+
78+
mapper.Class<EntityMultiInterfaces>(
79+
rc =>
80+
{
81+
rc.Id(x => x.Id);
82+
rc.Property(x => x.Name);
83+
});
84+
85+
mapper.Class<EntityMixExplicitImplicitInterface>(
86+
rc =>
87+
{
88+
rc.Table("multiInterface");
89+
rc.Id(x => x.Id);
90+
rc.Property(x => x.Name);
91+
});
92+
93+
mapper.Class<EntityMultiIdProxy>(
94+
rc =>
95+
{
96+
rc.Proxy(typeof(IMultiIdProxy));
97+
rc.Id(x => x.Id);
98+
rc.Property(x => x.Name);
99+
});
100+
101+
return mapper.CompileMappingForAllExplicitlyAddedEntities();
102+
}
103+
104+
[Test]
105+
public async Task ProxyForBaseSubclassCanBeCreatedAsync()
106+
{
107+
using (var session = OpenSession())
108+
{
109+
var entity = await (session.LoadAsync<EntityClassProxy>(_id));
110+
}
111+
}
112+
113+
//Id access via implicit interface should not lead to proxy initialization
114+
[Test]
115+
public async Task ProxyClassIdAccessByImplicitInterfaceAsync()
116+
{
117+
using (var session = OpenSession())
118+
{
119+
var entity = (IEntity) await (session.LoadAsync<EntitySimple>(_id));
120+
CanAccessIEntityId(entity);
121+
ThrowOnIEntityNameAccess(entity);
122+
Assert.That(entity.Id, Is.EqualTo(_id));
123+
124+
var multiInterface = await (session.LoadAsync<EntityMultiInterfaces>(_id));
125+
CanAccessIEntityId(multiInterface);
126+
CanAccessIEntity2Id(multiInterface);
127+
Assert.That(multiInterface.Id, Is.EqualTo(_id));
128+
}
129+
}
130+
131+
[Test]
132+
public async Task ProxyClassIdAccessExplicitInterfaceAsync()
133+
{
134+
using (var session = OpenSession())
135+
{
136+
var entity = await (session.LoadAsync<EntityExplicitInterface>(_id));
137+
138+
ThrowOnIEntityIdAccess(entity);
139+
Assert.That(entity.Id, Is.EqualTo(_id));
140+
}
141+
}
142+
143+
[Test]
144+
public async Task ProxyClassIdAccessBothImplicitExplicitInterfacesAsync()
145+
{
146+
using (var session = OpenSession())
147+
{
148+
var entity = await (session.LoadAsync<EntityMixExplicitImplicitInterface>(_id));
149+
150+
//IEntity2 is implicit and should be accessible without proxy initialization
151+
CanAccessIEntity2Id(entity);
152+
ThrowOnIEntityIdAccess(entity);
153+
}
154+
}
155+
156+
[Test]
157+
public async Task ProxyInterfaceIdAccessAsync()
158+
{
159+
using (var session = OpenSession())
160+
{
161+
var entity = await (session.LoadAsync<ISubEntityProxy>(_id));
162+
163+
CanAccessIEntityId(entity);
164+
}
165+
}
166+
167+
[KnownBug("GH-2271")]
168+
[Test]
169+
public async Task ProxyInterfaceIdAccessFromDifferentInterfacesAsync()
170+
{
171+
using (var session = OpenSession())
172+
{
173+
var entity = await (session.LoadAsync<IMultiIdProxy>(_id));
174+
175+
CanAccessIEntityId(entity);
176+
CanAccessIEntity2Id(entity);
177+
}
178+
}
179+
180+
private void ThrowOnIEntityNameAccess(IEntity entity)
181+
{
182+
Assert.That(() => entity.Name, Throws.TypeOf<ObjectNotFoundException>(), "IEntity.Name access should lead to proxy initialization");
183+
}
184+
185+
private void ThrowOnIEntityIdAccess(IEntity entity)
186+
{
187+
Assert.That(() => entity.Id, Throws.TypeOf<ObjectNotFoundException>(), "IEntity.Id access should lead to proxy initialization");
188+
}
189+
190+
private void CanAccessIEntityId(IEntity entity)
191+
{
192+
Assert.That(() => entity.Id, Throws.Nothing, "Failed to access proxy IEntity.Id interface");
193+
Assert.That(entity.Id, Is.EqualTo(_id));
194+
}
195+
196+
private void CanAccessIEntity2Id(IEntity2 entity)
197+
{
198+
Assert.That(() => entity.Id, Throws.Nothing, "Failed to access proxy IEntity2.Id interface");
199+
Assert.That(entity.Id, Is.EqualTo(_id));
200+
}
201+
}
202+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
3+
namespace NHibernate.Test.StaticProxyTest.InterfaceHandling
4+
{
5+
public interface IEntity
6+
{
7+
Guid Id { get; set; }
8+
9+
string Name { get; set; }
10+
}
11+
12+
public interface IEntity2
13+
{
14+
Guid Id { get; set; }
15+
}
16+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
using System;
2+
3+
namespace NHibernate.Test.StaticProxyTest.InterfaceHandling
4+
{
5+
public class EntitySimple : IEntity
6+
{
7+
public virtual Guid Id { get; set; }
8+
9+
public virtual string Name { get; set; }
10+
}
11+
12+
public class EntityMultiInterfaces : IEntity, IEntity2
13+
{
14+
public virtual Guid Id { get; set; }
15+
16+
public virtual string Name { get; set; }
17+
}
18+
19+
public class EntityExplicitInterface : IEntity
20+
{
21+
private Guid id;
22+
private string name;
23+
24+
public virtual Guid Id { get; set; }
25+
26+
public virtual string Name { get; set; }
27+
28+
Guid IEntity.Id
29+
{
30+
get => id;
31+
set => id = value;
32+
}
33+
34+
string IEntity.Name
35+
{
36+
get => name;
37+
set => name = value;
38+
}
39+
}
40+
41+
//Proxy contains IEntity.Id and IEntity2.Id
42+
public interface IMultiIdProxy : IEntity, IEntity2
43+
{
44+
}
45+
46+
public class EntityMultiIdProxy : IMultiIdProxy
47+
{
48+
public virtual Guid Id { get; set; }
49+
public virtual string Name { get; set; }
50+
}
51+
52+
public class EntityMixExplicitImplicitInterface : IEntity, IEntity2
53+
{
54+
private Guid id;
55+
private string name;
56+
57+
public virtual Guid Id { get; set; }
58+
59+
public virtual string Name { get; set; }
60+
61+
Guid IEntity.Id
62+
{
63+
get => id;
64+
set => id = value;
65+
}
66+
67+
string IEntity.Name
68+
{
69+
get => name;
70+
set => name = value;
71+
}
72+
}
73+
74+
public class EntityWithSuperClassInterfaceLookup
75+
{
76+
public virtual Guid Id { get; set; }
77+
78+
public virtual string Name { get; set; }
79+
80+
public virtual IEntity EntityLookup { get; set; }
81+
}
82+
}

0 commit comments

Comments
 (0)