diff --git a/src/Api.php b/src/Api.php
index d81bbc8..5bba99f 100644
--- a/src/Api.php
+++ b/src/Api.php
@@ -11,6 +11,7 @@ use Zoomyboy\LaravelNami\Authentication\Authenticator;
 use Zoomyboy\LaravelNami\Data\Baustein;
 use Zoomyboy\LaravelNami\Data\Course;
 use Zoomyboy\LaravelNami\Data\Member;
+use Zoomyboy\LaravelNami\Data\MemberEntry;
 use Zoomyboy\LaravelNami\Data\Membership;
 use Zoomyboy\LaravelNami\Data\MembershipEntry;
 use Zoomyboy\LaravelNami\Exceptions\NotAuthenticatedException;
@@ -31,7 +32,7 @@ class Api
         return $this->authenticator->http();
     }
 
-    public function findNr(int $nr): Member
+    public function findNr(int $nr): ?MemberEntry
     {
         $this->assertLoggedIn();
 
@@ -41,7 +42,7 @@ class Api
     /**
      * @param array<string, mixed> $payload
      */
-    public function find(array $payload): ?Member
+    public function find(array $payload): ?MemberEntry
     {
         $this->assertLoggedIn();
 
@@ -51,7 +52,7 @@ class Api
     /**
      * @param array<string, mixed> $payload
      *
-     * @return LazyCollection<int, Member>
+     * @return LazyCollection<int, MemberEntry>
      */
     public function search(array $payload): LazyCollection
     {
@@ -64,9 +65,7 @@ class Api
                     $this->exception('Search failed', '', $response->json(), []);
                 }
                 foreach ($response->json()['data'] as $member) {
-                    yield Member::fromNami(collect($member)->mapWithKeys(function ($value, $key) {
-                        return [str_replace('entries_', '', (string) $key) => $value];
-                    }));
+                    yield MemberEntry::from($member);
                 }
             },
             fn ($response) => $response->json()['totalEntries'],
@@ -111,12 +110,11 @@ class Api
         );
     }
 
-    public function putMember(array $attributes): array
+    public function putMember(Member $member): int
     {
         $this->assertLoggedIn();
-        $member = Member::fromAttributes($attributes);
-        if (data_get($attributes, 'id')) {
-            $existing = $this->member($member->group_id, $member->id);
+        if ($member->id) {
+            $existing = $this->member($member->groupId, $member->id);
             $payload = array_merge($existing, $member->toNami());
             $payload['kontoverbindung'] = json_encode(data_get($payload, 'kontoverbindung', []));
             $url = $this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$member->group_id.'/'.$member->id;
@@ -125,13 +123,13 @@ class Api
                 $this->exception('Update failed', $url, $response->json(), $member->toNami());
             }
         } else {
-            $url = $this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$member->group_id;
+            $url = $this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$member->groupId;
             $response = $this->http()->post($url, $member->toNami());
             if (true !== data_get($response->json(), 'success')) {
                 $this->exception('Update failed', $url, $response->json(), $member->toNami());
             }
 
-            return ['id' => $response->json()['data']];
+            return $response->json()['data'];
         }
 
         return $response->json()['data'];
@@ -215,7 +213,7 @@ class Api
         $this->assertLoggedIn();
 
         return $this->fetchCollection('/ica/rest/module/baustein', 'Fetch courses failed')
-            ->map(fn ($course) => new Baustein($course));
+            ->map(fn ($course) => Baustein::from($course));
     }
 
     /**
@@ -234,7 +232,7 @@ class Api
     {
         $single = $this->fetchData("/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/{$courseId}", 'Error fetching single course');
 
-        return $single ? new Course($single) : null;
+        return $single ? Course::from($single) : null;
     }
 
     /**
diff --git a/src/Data/Course.php b/src/Data/Course.php
index 960511b..6c6aa91 100644
--- a/src/Data/Course.php
+++ b/src/Data/Course.php
@@ -2,22 +2,25 @@
 
 namespace Zoomyboy\LaravelNami\Data;
 
-use Spatie\DataTransferObject\Attributes\MapFrom;
-use Spatie\DataTransferObject\DataTransferObject;
+use Spatie\LaravelData\Attributes\MapInputName;
+use Spatie\LaravelData\Data;
 
-class Course extends DataTransferObject
+class Course extends Data
 {
-    public int $id;
+    public function __construct(
+        public int $id,
 
-    #[MapFrom('bausteinId')]
-    public string $courseId;
+        #[MapInputName('bausteinId')]
+        public string $courseId,
 
-    #[MapFrom('veranstalter')]
-    public string $organizer;
+        #[MapInputName('veranstalter')]
+        public string $organizer,
 
-    #[MapFrom('vstgName')]
-    public string $eventName;
+        #[MapInputName('vstgName')]
+        public string $eventName,
 
-    #[MapFrom('vstgTag')]
-    public string $completedAt;
+        #[MapInputName('vstgTag')]
+        public string $completedAt,
+    ) {
+    }
 }
diff --git a/src/Data/EnumData.php b/src/Data/EnumData.php
index b0b3a9a..dc8e1bf 100644
--- a/src/Data/EnumData.php
+++ b/src/Data/EnumData.php
@@ -2,13 +2,13 @@
 
 namespace Zoomyboy\LaravelNami\Data;
 
-use Spatie\DataTransferObject\Attributes\MapFrom;
-use Spatie\DataTransferObject\DataTransferObject;
+use Spatie\LaravelData\Attributes\MapInputName;
+use Spatie\LaravelData\Data;
 
-abstract class EnumData extends DataTransferObject
+abstract class EnumData extends Data
 {
     public int $id;
 
-    #[MapFrom('descriptor')]
+    #[MapInputName('descriptor')]
     public string $name;
 }
diff --git a/src/Data/Member.php b/src/Data/Member.php
index 66b0a68..1670a56 100644
--- a/src/Data/Member.php
+++ b/src/Data/Member.php
@@ -2,18 +2,133 @@
 
 namespace Zoomyboy\LaravelNami\Data;
 
+use Carbon\Carbon;
 use Spatie\LaravelData\Attributes\MapInputName;
+use Spatie\LaravelData\Attributes\WithCast;
 use Spatie\LaravelData\Data;
+use Zoomyboy\LaravelNami\Casters\CarbonCast;
+use Zoomyboy\LaravelNami\Casters\StringCast;
 
 class Member extends Data
 {
     public function __construct(
         #[MapInputName('vorname')]
-        public string $firstname,
+        #[WithCast(StringCast::class)]
+        public ?string $firstname,
+
         #[MapInputName('nachname')]
-        public string $lastname,
+        #[WithCast(StringCast::class)]
+        public ?string $lastname,
+
         #[MapInputName('spitzname')]
-        public string $nickname,
+        #[WithCast(StringCast::class)]
+        public ?string $nickname,
+
+        #[MapInputName('beitragsartId')]
+        public ?int $feeId,
+
+        #[MapInputName('eintrittsdatum')]
+        #[WithCast(CarbonCast::class, format: 'Y-m-d H:i:s')]
+        public Carbon $joinedAt,
+
+        #[MapInputName('geburtsDatum')]
+        #[WithCast(CarbonCast::class, format: 'Y-m-d H:i:s')]
+        public Carbon $birthday,
+
+        public string $email,
+
+        #[MapInputName('geschlechtId')]
+        public int $genderId,
+
+        #[MapInputName('konfessionId')]
+        public ?int $confessionId,
+
+        #[MapInputName('landId')]
+        public int $countryId,
+
+        #[MapInputName('lastUpdated')]
+        #[WithCast(CarbonCast::class, format: 'Y-m-d H:i:s')]
+        public ?Carbon $updatedAt,
+
+        #[MapInputName('nameZusatz')]
+        #[WithCast(StringCast::class)]
+        public ?string $furtherAddress,
+
+        #[MapInputName('emailVertretungsberechtigter')]
+        #[WithCast(StringCast::class)]
+        public ?string $emailParents,
+
+        public ?int $id,
+
+        #[MapInputName('gruppierungId')]
+        public int $groupId,
+
+        #[MapInputName('mitgliedsNummer')]
+        public ?int $memberId,
+
+        #[MapInputName('plz')]
+        public ?string $zip,
+
+        #[MapInputName('ort')]
+        public ?string $location,
+
+        public int $regionId,
+
+        #[MapInputName('staatsangehoerigkeitId')]
+        public int $nationalityId,
+
+        #[MapInputName('strasse')]
+        public ?string $address,
+
+        #[MapInputName('telefax')]
+        #[WithCast(StringCast::class)]
+        public ?string $fax,
+
+        #[MapInputName('telefon1')]
+        #[WithCast(StringCast::class)]
+        public ?string $mainPhone,
+
+        #[MapInputName('telefon2')]
+        #[WithCast(StringCast::class)]
+        public ?string $mobilePhone,
+
+        #[MapInputName('telefon3')]
+        #[WithCast(StringCast::class)]
+        public ?string $workPhone,
+
+        #[MapInputName('staatsangehoerigkeitText')]
+        #[WithCast(StringCast::class)]
+        public ?string $otherCountry,
+
+        public ?int $version,
+
+        #[MapInputName('wiederverwendenFlag')]
+        public bool $keepdata,
+
+        #[MapInputName('zeitschriftenversand')]
+        public bool $sendNewspaper,
     ) {
     }
+
+    /**
+     * @return array<string, mixed>
+     */
+    public function toNami(): array
+    {
+        return [
+            'spitzname' => $this->nickname ?: '',
+            'vorname' => $this->firstname ?: '',
+            'nachname' => $this->lastname ?: '',
+            'geschlechtId' => $this->genderId,
+            'email' => $this->email,
+            'beitragsartId' => $this->feeId,
+            'geburtsDatum' => $this->birthday->format('Y-m-d 00:00:00'),
+            'konfessionId' => $this->confessionId,
+            'landId' => $this->countryId,
+            'wiederverwendenFlag' => $this->keepdata,
+            'regionId' => $this->regionId,
+            'staatsangehoerigkeitId' => $this->nationalityId,
+            'zeitschriftenversand' => $this->sendNewspaper,
+        ];
+    }
 }
diff --git a/src/Data/MemberEntry.php b/src/Data/MemberEntry.php
new file mode 100644
index 0000000..8927d23
--- /dev/null
+++ b/src/Data/MemberEntry.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Zoomyboy\LaravelNami\Data;
+
+use Spatie\LaravelData\Attributes\MapInputName;
+use Spatie\LaravelData\Attributes\WithCast;
+use Spatie\LaravelData\Data;
+use Zoomyboy\LaravelNami\Casters\StringCast;
+
+class MemberEntry extends Data
+{
+    public function __construct(
+        #[MapInputName('entries_vorname')]
+        #[WithCast(StringCast::class)]
+        public ?string $firstname,
+
+        #[MapInputName('entries_nachname')]
+        #[WithCast(StringCast::class)]
+        public ?string $lastname,
+    ) {
+    }
+}
diff --git a/src/Fakes/MemberFake.php b/src/Fakes/MemberFake.php
index a583244..431f36d 100644
--- a/src/Fakes/MemberFake.php
+++ b/src/Fakes/MemberFake.php
@@ -23,20 +23,36 @@ class MemberFake extends Fake
             $url = 'https://nami.dpsg.de/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/'.$memberId;
             if ($request->url() === $url && 'GET' === $request->method()) {
                 return $this->dataResponse(array_merge([
-                    'id' => $memberId,
-                    'vorname' => '::firstname::',
-                    'nachname' => '::lastname::',
-                    'zeitschriftenversand' => true,
-                    'strasse' => '::address::',
-                    'plz' => '12345',
-                    'ort' => 'SG',
-                    'version' => 1,
+                    'beitragsartId' => 1,
                     'eintrittsdatum' => '2005-05-01 00:00:00',
+                    'email' => 'pille@stamm-silva.de',
+                    'emailVertretungsberechtigter' => '',
                     'geburtsDatum' => '1991-06-20 00:00:00',
-                    'gruppierungId' => $groupId,
-                    'gruppierung' => 'gei0OhSh0quahcoh',
                     'geschlechtId' => 19,
+                    'gruppierung' => 'gei0OhSh0quahcoh',
+                    'gruppierungId' => $groupId,
+                    'mitgliedsNummer' => 55,
+                    'id' => $memberId,
+                    'konfessionId' => 1,
+                    'landId' => 1,
+                    'lastUpdated' => '2022-03-20 11:58:33',
+                    'nachname' => '::lastname::',
+                    'nameZusatz' => 'zuss',
+                    'ort' => 'SG',
+                    'plz' => '12345',
+                    'regionId' => 10,
+                    'spitzname' => 'pille',
                     'staatsangehoerigkeitId' => 1054,
+                    'staatsangehoerigkeitText' => '',
+                    'strasse' => '::address::',
+                    'telefax' => '+49 176 44333',
+                    'telefon1' => '+49 212 1399418',
+                    'telefon2' => '+49 176 555555',
+                    'telefon3' => '+49 176 5544466',
+                    'version' => 1,
+                    'vorname' => '::firstname::',
+                    'wiederverwendenFlag' => false,
+                    'zeitschriftenversand' => true,
                 ], $data));
             }
         });
@@ -115,7 +131,7 @@ class MemberFake extends Fake
             $requestBody = json_decode($request->body(), true);
 
             foreach ($body as $key => $value) {
-                if (!isset($requestBody[$key])) {
+                if (!array_key_exists($key, $requestBody)) {
                     return false;
                 }
 
diff --git a/src/Fakes/SubactivityFake.php b/src/Fakes/SubactivityFake.php
index 4ccfe25..755d3f1 100644
--- a/src/Fakes/SubactivityFake.php
+++ b/src/Fakes/SubactivityFake.php
@@ -6,6 +6,21 @@ use Illuminate\Support\Facades\Http;
 
 class SubactivityFake extends Fake
 {
+    /**
+     * @param array<int, array{descriptor: string, id: int}> $data
+     */
+    public function fetches(int $activityId, array $data): self
+    {
+        Http::fake(function ($request) use ($data, $activityId) {
+            $url = "https://nami.dpsg.de/ica/rest/nami/untergliederungauftaetigkeit/filtered/untergliederung/taetigkeit/$activityId";
+            if ($request->url() === $url && 'GET' === $request->method()) {
+                return $this->dataResponse($data);
+            }
+        });
+
+        return $this;
+    }
+
     public function fetchFails(int $activityId, ?string $error = 'wrong message'): void
     {
         Http::fake(function ($request) use ($activityId, $error) {
diff --git a/tests/Unit/Api/FetchMemberTest.php b/tests/Unit/Api/FetchMemberTest.php
new file mode 100644
index 0000000..31f5542
--- /dev/null
+++ b/tests/Unit/Api/FetchMemberTest.php
@@ -0,0 +1,118 @@
+<?php
+
+namespace Zoomyboy\LaravelNami\Tests\Unit\Member;
+
+use Zoomyboy\LaravelNami\Fakes\MemberFake;
+use Zoomyboy\LaravelNami\NamiException;
+use Zoomyboy\LaravelNami\Tests\TestCase;
+
+class FetchMemberTest extends TestCase
+{
+    public function testGetASingleMember(): void
+    {
+        app(MemberFake::class)->shows(1000, 1001, [
+            'beitragsartId' => 1,
+            'eintrittsdatum' => '2005-05-01 00:00:00',
+            'email' => 'pille@stamm-silva.de',
+            'emailVertretungsberechtigter' => 'aa@b.de',
+            'geburtsDatum' => '1991-06-20 00:00:00',
+            'geschlechtId' => 19,
+            'konfessionId' => 1,
+            'landId' => 1,
+            'lastUpdated' => '2022-03-20 11:58:33',
+            'nachname' => 'Lang',
+            'nameZusatz' => 'zuss',
+            'ort' => 'Solingen',
+            'plz' => '42719',
+            'regionId' => 10,
+            'spitzname' => 'pille',
+            'staatsangehoerigkeitId' => 1054,
+            'staatsangehoerigkeitText' => 'lorem',
+            'strasse' => 'Maxstr 5',
+            'telefax' => '+49 176 44333',
+            'telefon1' => '+49 212 1399418',
+            'telefon2' => '+49 176 555555',
+            'telefon3' => '+49 176 5544466',
+            'version' => 161,
+            'vorname' => 'Philipp',
+            'wiederverwendenFlag' => false,
+            'zeitschriftenversand' => true,
+            'mitgliedsNummer' => 53,
+        ]);
+
+        $member = $this->login()->member(1000, 1001);
+
+        $this->assertSame(1, $member->feeId);
+        $this->assertSame('2005-05-01 00:00:00', $member->joinedAt->toDateTimeString());
+        $this->assertSame(1000, $member->groupId);
+        $this->assertSame(1001, $member->id);
+        $this->assertSame('pille@stamm-silva.de', $member->email);
+        $this->assertSame('1991-06-20 00:00:00', $member->birthday->toDateTimeString());
+        $this->assertSame(19, $member->genderId);
+        $this->assertSame('aa@b.de', $member->emailParents);
+        $this->assertSame(53, $member->memberId);
+        $this->assertSame(1, $member->confessionId);
+        $this->assertSame(1, $member->countryId);
+        $this->assertSame('2022-03-20 11:58:33', $member->updatedAt->toDateTimeString());
+        $this->assertSame('Lang', $member->lastname);
+        $this->assertSame('zuss', $member->furtherAddress);
+        $this->assertSame('Solingen', $member->location);
+        $this->assertSame('42719', $member->zip);
+        $this->assertSame(10, $member->regionId);
+        $this->assertSame('pille', $member->nickname);
+        $this->assertSame(1054, $member->nationalityId);
+        $this->assertSame('lorem', $member->otherCountry);
+        $this->assertSame('Maxstr 5', $member->address);
+        $this->assertSame('+49 176 44333', $member->fax);
+        $this->assertSame('+49 212 1399418', $member->mainPhone);
+        $this->assertSame('+49 176 555555', $member->mobilePhone);
+        $this->assertSame('+49 176 5544466', $member->workPhone);
+        $this->assertSame(161, $member->version);
+        $this->assertSame('Philipp', $member->firstname);
+        $this->assertSame(false, $member->keepdata);
+        $this->assertSame(true, $member->sendNewspaper);
+    }
+
+    public function testGetMinimalData(): void
+    {
+        app(MemberFake::class)->shows(1000, 1001, [
+            'vorname' => '',
+            'nachname' => '',
+            'nameZusatz' => '',
+            'spitzname' => '',
+            'telefax' => '',
+            'telefon1' => '',
+            'telefon2' => '',
+            'telefon3' => '',
+            'staatsangehoerigkeitText' => '',
+            'emailVertretungsberechtigter' => '',
+            'mitgliedsNummer' => null,
+            'beitragsartId' => null,
+            'konfessionId' => null,
+        ]);
+
+        $member = $this->login()->member(1000, 1001);
+
+        $this->assertNull($member->lastname);
+        $this->assertNull($member->firstname);
+        $this->assertNull($member->furtherAddress);
+        $this->assertNull($member->nickname);
+        $this->assertnull($member->fax);
+        $this->assertnull($member->mainPhone);
+        $this->assertnull($member->mobilePhone);
+        $this->assertnull($member->workPhone);
+        $this->assertnull($member->otherCountry);
+        $this->assertNull($member->emailParents);
+        $this->assertNull($member->memberId);
+        $this->assertNull($member->feeId);
+        $this->assertNull($member->confessionId);
+    }
+
+    public function testMemberFetchCanFail(): void
+    {
+        $this->expectException(NamiException::class);
+        app(MemberFake::class)->fetchFails(103, 16);
+
+        $this->login()->member(103, 16);
+    }
+}
diff --git a/tests/Unit/Member/PullTest.php b/tests/Unit/Member/PullTest.php
deleted file mode 100644
index 5d3fecf..0000000
--- a/tests/Unit/Member/PullTest.php
+++ /dev/null
@@ -1,199 +0,0 @@
-<?php
-
-namespace Zoomyboy\LaravelNami\Tests\Unit\Member;
-
-use Illuminate\Support\Facades\Http;
-use Zoomyboy\LaravelNami\Fakes\MemberFake;
-use Zoomyboy\LaravelNami\NamiException;
-use Zoomyboy\LaravelNami\Tests\Factories\MemberRequestFactory;
-use Zoomyboy\LaravelNami\Tests\TestCase;
-
-class PullTest extends TestCase
-{
-    public string $groupsResponse = '{"success":true,"data":[{"descriptor":"Group","name":"","representedClass":"de.iconcept.nami.entity.org.Gruppierung","id":103}],"responseType":"OK"}';
-    public string $unauthorizedResponse = '{"success":false,"data":null,"responseType":"EXCEPTION","message":"Access denied - no right for requested operation","title":"Exception"}';
-
-    public function dataProvider(): array
-    {
-        return [
-            'firstname' => [['vorname' => 'Max'], ['firstname' => 'Max']],
-            'lastname' => [['nachname' => 'Nach'], ['lastname' => 'Nach']],
-            'nickname' => [['spitzname' => 'spitz1'], ['nickname' => 'spitz1']],
-            'nicknameEmpty' => [['spitzname' => null], ['nickname' => null]],
-            'other_country' => [['staatsangehoerigkeitText' => 'deutsch'], ['other_country' => 'deutsch']],
-            'other_countryEmpty' => [['staatsangehoerigkeitText' => ''], ['other_country' => null]],
-            'address' => [['strasse' => 'Straße 1'], ['address' => 'Straße 1']],
-            'further_address' => [['nameZusatz' => 'addrz'], ['further_address' => 'addrz']],
-            'further_addressEmpty' => [['nameZusatz' => ''], ['further_address' => null]],
-            'zip' => [['plz' => '12345'], ['zip' => '12345']],
-            'location' => [['ort' => 'Köln'], ['location' => 'Köln']],
-            'main_phone' => [['telefon1' => '+49888'], ['main_phone' => '+49888']],
-            'mobile_phone' => [['telefon2' => '+49176'], ['mobile_phone' => '+49176']],
-            'work_phone' => [['telefon3' => '+49177'], ['work_phone' => '+49177']],
-            'fax' => [['telefax' => '+55111'], ['fax' => '+55111']],
-            'email' => [['email' => 'a@b.de'], ['email' => 'a@b.de']],
-            'email_parents' => [['emailVertretungsberechtigter' => 'v@b.de'], ['email_parents' => 'v@b.de']],
-            'gender_id' => [['geschlechtId' => 19], ['gender_id' => 19]],
-            'gender_idEmpty' => [['geschlechtId' => 23], ['gender_id' => null]],
-            'nationality_id' => [['staatsangehoerigkeitId' => 1054], ['nationality_id' => 1054]],
-            'nationality_idEmpty' => [['staatsangehoerigkeitId' => null], ['nationality_id' => null]],
-            'confession_id' => [['konfessionId' => 1], ['confession_id' => 1]],
-            'confession_idEmpty' => [['konfessionId' => null], ['confession_id' => null]],
-            'birthday' => [['geburtsDatum' => '1991-06-20 00:00:00'], ['birthday' => '1991-06-20']],
-            'joined_at' => [['eintrittsdatum' => '2005-05-01 00:00:00'], ['joined_at' => '2005-05-01']],
-            'group_id' => [['gruppierungId' => 103], ['group_id' => 103]],
-            'mitgliedsnr' => [['mitgliedsNummer' => 12345], ['mitgliedsnr' => 12345]],
-            'mitgliedsnrEmpty' => [['mitgliedsNummer' => null], ['mitgliedsnr' => null]],
-            'updated_at' => [['lastUpdated' => '2020-06-28 02:15:24'], ['updated_at' => '2020-06-28 02:15:24']],
-            'send_newspaper' => [['zeitschriftenversand' => true], ['send_newspaper' => true]],
-            'region_id' => [['regionId' => 10], ['region_id' => 10]],
-            'region_idEmpty' => [['regionId' => null], ['region_id' => null]],
-            'country_id' => [['landId' => 100], ['country_id' => 100]],
-            'fee_id' => [['beitragsartId' => 1], ['fee_id' => 1]],
-        ];
-    }
-
-    public function overviewDataProvider(): array
-    {
-        return [
-            'firstname' => ['firstname', ['Max', 'Jane']],
-            'lastname' => ['lastname', ['Nach1', 'Nach2']],
-            'nickname' => ['nickname', ['spitz1', null]],
-            'other_country' => ['other_country', ['deutsch', null]],
-            'main_phone' => ['main_phone', ['+49888', '+49668']],
-            'mobile_phone' => ['mobile_phone', ['+49176', '+49172']],
-            'work_phone' => ['work_phone', ['+11111', '+22222']],
-            'fax' => ['fax', ['+55111', '+55222']],
-            'email' => ['email', ['test@example.com', 'test2@example.com']],
-            'email_parents' => ['email_parents', ['testp@example.com', 'test2p@example.com']],
-            'gender_id' => ['gender_id', [19, null]],
-            'birthday' => ['birthday', ['1991-06-20', '1984-01-17']],
-            'joined_at' => ['joined_at', ['2005-05-01', null]],
-            'group_id' => ['group_id', [103, 103]],
-            'mitgliedsnr' => ['mitgliedsnr', [12345, null]],
-            'updated_at' => ['updated_at', ['2020-06-28 02:15:24', '2015-02-03 15:20:07']],
-        ];
-    }
-
-    public function relationProvider(): array
-    {
-        return [
-            'firstname' => ['firstname', ['Max', 'Jane']],
-        ];
-    }
-
-    public function testGetASingleMember(): void
-    {
-        Http::fake([
-            'https://nami.dpsg.de/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/103/16' => MemberRequestFactory::new()->state([
-                'vorname' => 'Max',
-                'nachname' => 'Nach',
-                'spitzname' => 'spitz1',
-            ])->toSingleHttp(),
-        ]);
-
-        $member = $this->login()->member(103, 16);
-
-        $this->assertEquals('Max', $member->firstname);
-        $this->assertEquals('Nach', $member->lastname);
-        $this->assertEquals('spitz1', $member->nickname);
-    }
-
-    public function testGetASingleMemberWithEmptyNames(): void
-    {
-        Http::fake([
-            'https://nami.dpsg.de/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/103/16' => MemberRequestFactory::new()->withEmptyNames()->toSingleHttp(),
-        ]);
-
-        $member = $this->login()->member(103, 16);
-
-        $this->assertNull($member->firstname);
-        $this->assertNull($member->lastname);
-        $this->assertNull($member->nickname);
-    }
-
-    /**
-     * @dataProvider dataProvider
-     */
-    public function testGetAttributeOfMemberCollection(array $input, array $check): void
-    {
-        Http::fake([
-            'https://nami.dpsg.de/ica/rest/nami/gruppierungen/filtered-for-navigation/gruppierung/node/root' => Http::response($this->groupsResponse, 200),
-            'https://nami.dpsg.de/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/103/flist' => Http::response($this->fakeJson('member_overview.json'), 200),
-            'https://nami.dpsg.de/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/103/16' => Http::response($this->fakeJson('member-16.json', ['data' => $input]), 200),
-        ]);
-
-        $member = $this->login()->group(103)->members()->first();
-
-        foreach ($check as $key => $value) {
-            $this->assertSame($value, $member->toArray()[$key]);
-        }
-        Http::assertSentCount(3);
-    }
-
-    /**
-     * @dataProvider overviewDataProvider
-     */
-    public function testGetAttributeOfMemberOverview(string $key, array $values): void
-    {
-        Http::fake([
-            'https://nami.dpsg.de/ica/rest/nami/gruppierungen/filtered-for-navigation/gruppierung/node/root' => Http::response($this->groupsResponse, 200),
-            'https://nami.dpsg.de/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/103/flist' => Http::response($this->fakeJson('member_overview.json'), 200),
-        ]);
-
-        $members = $this->login()->group(103)->memberOverview();
-        foreach ($members as $i => $m) {
-            $this->assertSame($values[$i], $m->toArray()[$key]);
-        }
-
-        Http::assertSentCount(2);
-    }
-
-    /**
-     * @dataProvider relationProvider
-     */
-    public function testSetRelations(string $key, array $values): void
-    {
-        Http::fake([
-            'https://nami.dpsg.de/ica/rest/nami/gruppierungen/filtered-for-navigation/gruppierung/node/root' => Http::response($this->groupsResponse, 200),
-            'https://nami.dpsg.de/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/103/flist' => Http::response($this->fakeJson('member_overview.json'), 200),
-            'https://nami.dpsg.de/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/103/16' => Http::response($this->fakeJson('member-16.json'), 200),
-            'https://nami.dpsg.de/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/103/17' => Http::response($this->fakeJson('member-17.json'), 200),
-        ]);
-
-        $members = $this->login()->group(103)->members();
-
-        $this->assertSame([
-            16 => $values[0],
-            17 => $values[1],
-        ], $members->pluck($key, 'id')->toArray());
-
-        Http::assertSentCount(4);
-    }
-
-    /**
-     * @dataProvider overviewDataProvider
-     */
-    public function testGetAMemberFromOverviewWithNoRights(string $key, array $values): void
-    {
-        Http::fake([
-            'https://nami.dpsg.de/ica/rest/nami/gruppierungen/filtered-for-navigation/gruppierung/node/root' => Http::response($this->groupsResponse, 200),
-            'https://nami.dpsg.de/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/103/16' => Http::response($this->unauthorizedResponse, 200),
-            'https://nami.dpsg.de/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/103/flist' => Http::response($this->fakeJson('member_overview.json'), 200),
-        ]);
-
-        $member = $this->login()->group(103)->member(16);
-
-        $this->assertSame($values[0], $member->toArray()[$key]);
-
-        Http::assertSentCount(3);
-    }
-
-    public function testMemberFetchCanFail(): void
-    {
-        $this->expectException(NamiException::class);
-        app(MemberFake::class)->fetchFails(103, 16);
-
-        $this->login()->member(103, 16);
-    }
-}
diff --git a/tests/Unit/Membership/MembershipTest.php b/tests/Unit/Membership/MembershipTest.php
deleted file mode 100644
index bff7eb0..0000000
--- a/tests/Unit/Membership/MembershipTest.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-namespace Zoomyboy\LaravelNami\Tests\Unit\Membership;
-
-use Zoomyboy\LaravelNami\Fakes\MembershipFake;
-use Zoomyboy\LaravelNami\Member;
-use Zoomyboy\LaravelNami\Tests\TestCase;
-
-class MembershipTest extends TestCase
-{
-    public function testGetMembershipsOfAMember(): void
-    {
-        app(MembershipFake::class)
-            ->fetches(16, [68])
-            ->shows(16, [
-                'id' => 68,
-            ]);
-        $this->login();
-        $member = new Member(['id' => 16]);
-
-        $membership = $member->memberships()->first();
-
-        $this->assertEquals(68, $membership->id);
-    }
-
-    /**
-     * @testWith ["Access denied - no right for requested operation", "Sicherheitsverletzung: Zugriff auf Rechte Recht (n:2001002 o:2) fehlgeschlagen"]
-     */
-    public function testItGetsNoMembershipsWithNoRights(string $error): void
-    {
-        app(MembershipFake::class)->failsFetching(16, $error);
-        $this->login();
-        $member = new Member(['id' => 16]);
-
-        $memberships = $member->memberships();
-
-        $this->assertSame([], $memberships->toArray());
-    }
-}
diff --git a/tests/Unit/Membership/PushMembershipsTest.php b/tests/Unit/Membership/PushMembershipsTest.php
index 23f516a..0be4feb 100644
--- a/tests/Unit/Membership/PushMembershipsTest.php
+++ b/tests/Unit/Membership/PushMembershipsTest.php
@@ -6,7 +6,6 @@ use Carbon\Carbon;
 use Illuminate\Support\Facades\Http;
 use Zoomyboy\LaravelNami\Data\Membership;
 use Zoomyboy\LaravelNami\Fakes\MembershipFake;
-use Zoomyboy\LaravelNami\Member;
 use Zoomyboy\LaravelNami\Tests\TestCase;
 
 class PushMembershipsTest extends TestCase
@@ -17,8 +16,7 @@ class PushMembershipsTest extends TestCase
         app(MembershipFake::class)->createsSuccessfully(16, 65);
         $this->login();
 
-        $member = new Member(['id' => 16]);
-        $id = $member->putMembership(Membership::fromArray([
+        $id = $this->login()->putMembership(16, Membership::from([
             'startsAt' => now(),
             'groupId' => 150,
             'activityId' => 56,
diff --git a/tests/Unit/PushMemberTest.php b/tests/Unit/PushMemberTest.php
index 150f990..1e272e4 100644
--- a/tests/Unit/PushMemberTest.php
+++ b/tests/Unit/PushMemberTest.php
@@ -2,72 +2,49 @@
 
 namespace Zoomyboy\LaravelNami\Tests\Unit;
 
-use Illuminate\Support\Facades\Http;
-use Zoomyboy\LaravelNami\Nami;
+use Zoomyboy\LaravelNami\Data\Member;
+use Zoomyboy\LaravelNami\Fakes\MemberFake;
 use Zoomyboy\LaravelNami\Tests\TestCase;
 
 class PushMemberTest extends TestCase
 {
-    public array $attributes = [
-        [
+    public function testPushASingleMember(): void
+    {
+        app(MemberFake::class)->createsSuccessfully(103, 16);
+        $response = $this->login()->putMember(Member::from([
             'firstname' => 'Max',
             'lastname' => 'Nach1',
-            'group_id' => 103,
             'nickname' => 'spitz1',
-            'gender_id' => 17,
-            'joined_at' => '2021-02-02T00:00:00',
-            'birthday' => '2021-02-02',
-            'id' => 16,
-        ], [
-            'firstname' => 'Jane',
-            'lastname' => 'Nach2',
-            'nickname' => null,
-            'group_id' => 103,
-            'gender_id' => null,
-            'joined_at' => '2021-02-02T00:00:00',
-            'birthday' => '2021-02-02',
-            'id' => 17,
-        ],
-    ];
+            'groupId' => 103,
+            'genderId' => 17,
+            'confessionId' => 33,
+            'joinedAt' => '2021-02-02 00:00:00',
+            'birthday' => '2021-02-02 00:00:00',
+            'email' => 'aa@b.de',
+            'countryId' => 78,
+            'keepdata' => false,
+            'sendNewspaper' => false,
+            'regionId' => 11,
+            'nationalityId' => 12,
+            'beitragsartId' => null,
+        ]));
 
-    public function dataProvider(): array
-    {
-        return [
-            'firstname' => [['firstname' => 'Max'], ['vorname' => 'Max']],
-            'lastname' => [['lastname' => 'Nach1'], ['nachname' => 'Nach1']],
-            'nickname' => [['nickname' => 'nick'], ['spitzname' => 'nick']],
-            'nicknameEmpty' => [['nickname' => null], ['spitzname' => '']],
-            'gender_id' => [['gender_id' => 17], ['geschlechtId' => 17]],
-        ];
-    }
+        $this->assertEquals(16, $response);
 
-    /**
-     * @dataProvider dataProvider
-     */
-    public function testPushASingleMember(array $overwrites, array $check): void
-    {
-        Http::fake([
-            'https://nami.dpsg.de/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/103/16' => Http::response('{"success": true, "data": {"id": 16}}', 200),
+        app(MemberFake::class)->assertCreated(103, [
+            'spitzname' => 'spitz1',
+            'vorname' => 'Max',
+            'nachname' => 'Nach1',
+            'geschlechtId' => 17,
+            'email' => 'aa@b.de',
+            'beitragsartId' => null,
+            'geburtsDatum' => '2021-02-02 00:00:00',
+            'konfessionId' => 33,
+            'landId' => 78,
+            'wiederverwendenFlag' => false,
+            'zeitschriftenversand' => false,
+            'regionId' => 11,
+            'staatsangehoerigkeitId' => 12,
         ]);
-        $this->login();
-
-        $res = Nami::putMember(array_merge($this->attributes[0], $overwrites));
-        $this->assertEquals(16, $res['id']);
-
-        Http::assertSent(function ($request) use ($check) {
-            if ('https://nami.dpsg.de/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/103/16' != $request->url() || 'PUT' !== $request->method()) {
-                return false;
-            }
-
-            foreach ($check as $key => $value) {
-                if ($request[$key] !== $value) {
-                    return false;
-                }
-            }
-
-            return 'PUT' === $request->method();
-        });
-
-        Http::assertSentCount(2);
     }
 }